-
Notifications
You must be signed in to change notification settings - Fork 235
Description
Bug Report
What did you do?
I have an operator implementation that was working well for some time, and then later started failing in an obscure, unintuitive way; the dependent would report ready but I could see from logs that much of the dependent code was not executed. In fact the state changes required for readiness were not being performed, and conditions that verified such changes (readyPostcondition) were being bypassed. No changes had been made to the operator implementation prior to the occurrence of this issue.
Eventually, using an Exception break-point, we traced the issue to a dependency update, that caused a java.lang.NoSuchFieldError to be thrown in the dependent.
What did you expect to see?
I expected that the NoSuchFieldError would be caught, register as an error in the dependent, prevent its readiness, and would be logged to aid the diagnosis of the root cause.
What did you see instead? Under which circumstances?
The NoSuchFieldError was seemingly swallowed, was not classed as an error in the context of the dependent, and in fact seemed to short-circuit in such a way that the dependent was marked as ready despite not executing most of my dependent logic. Critically, it was it was not logged, which greatly impeded diagnosis of the issue.
Note
The expectation that java.lang.Error should be handled may be contentious, as the JDK specifies that Error "indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions.". However, I'd argue that by effectively swallowing this class of exceptions, JOSDK ends up with insidious behaviours.
Environment
Kubernetes cluster type: k3s:1.31.0
java-operator-sdk.version: 5.1.1
via:
quarkus-operator-sdk.version: 7.2.0
via:
quarkus.version: 3.26.3
❯ java -version
openjdk version "21.0.7" 2025-04-15 LTS
OpenJDK Runtime Environment Temurin-21.0.7+6 (build 21.0.7+6-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.7+6 (build 21.0.7+6-LTS, mixed mode, sharing)
❯ kubectl version
Client Version: v1.30.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Possible Solution
Conceptually, it would seem that the part of the framework that invokes Dependents needs to also catch Throwable. Note that the code that invokes Reconcilers appears to handle this case correctly; when throwing a NoSuchFieldError from within a Reconciler.reconcile implementation, I observed that it is eventually caught and logged as we might expect. There may be other cases where the scope of exception handling of framework code calling user implementations needs to be broadened.
Additional context
Steps to reproduce:
- Pick a
Dependentimplementation - Override the
reconcilemethod, and simply throwNoSuchFieldError(NOTNoSuchFieldException) from within thereconcilemethod. - Reconcile your
Reconciler, observe that theDependentwill report as ready and no error will be logged by the framework.
@KubernetesDependent
@Dependent
public class MyDependent extends CRUDNoGCKubernetesDependentResource<Namespace, MyPrimary>
implements Creator<Namespace, MyPrimary>, Updater<Namespace, MyPrimary>, Deleter<MyPrimary> {
...
@Override
public ReconcileResult<Namespace> reconcile(MyPrimary primary, Context<MyPrimary> context) {
throw new NoSuchFieldError();
}
}