Skip to content

Error handling for Dependents is incomplete #3097

@teabot

Description

@teabot

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:

  1. Pick a Dependent implementation
  2. Override the reconcile method, and simply throw NoSuchFieldError (NOT NoSuchFieldException) from within the reconcile method.
  3. Reconcile your Reconciler, observe that the Dependent will 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();
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions