Skip to content

Cannot record events outside reconciliation loop or for arbitrary resources (RegisteredController#eventRecorder missing) #3686

Open

Description

@bertdw-1985

Bug Report

What did you do?

We attempted to record a Kubernetes event for our primary/main resource from within the reconciliation loop of a sub-resource / secondary controller, following the v5.6 release notes:
https://javaoperatorsdk.io/blog/2026/09/02/version-5.6-released/#kubernetes-event-recorder

According to the release documentation:

"Outside of the reconciliation loop — from a status listener or a background task, or about an object other than the primary — use the unbound form from RegisteredController#eventRecorder(), which is scoped to the controller rather than to a reconciliation:

EventRecorder recorder = registeredController.eventRecorder();
recorder.record(someOtherResource, EventRecord.normal("Noticed", "something happened"));

What did you expect to see?

  1. RegisteredController exposes an eventRecorder() method (or equivalent API) to obtain an unbound EventRecorder.
  2. EventRecorder provides a way to record events for an arbitrary target resource (e.g. recorder.record(someOtherResource, EventRecord.normal(...))), allowing a controller reconciling a sub-resource to emit an event on its main/parent resource.

What did you see instead? Under which circumstances?

  1. RegisteredController does not contain eventRecorder(). Calling registeredController.eventRecorder() fails to compile.
  2. In Context<P>, eventRecorder() returns a ResourceEventRecorder strictly bound to context.getPrimaryResource().
  3. In DefaultEventRecorder, toEvent(...) hardcodes the target resource to context.getPrimaryResource():
    var regarding = context.getPrimaryResource();
    and EventRecorder#record only accepts (EventRecord event, Context<?> context).

As a result, when reconciling a sub-resource (where context.getPrimaryResource() is the sub-resource), there is no supported way to publish an event targeting the main/parent resource.

Environment

Kubernetes cluster type: any
java-operator-sdk version: 5.6.3
java -version: 17 / 21
kubectl version: 1.30+

Possible Solution

Tracing through the PR history:

  • PR feat: Add Event Recorder #3570 (feat: Add Event Recorder) originally introduced RegisteredController#eventRecorder() and supported recording events for arbitrary objects.
  • PR refactor: configurable event recorder #3581 (refactor: configurable event recorder) refactored the API to be stateless and removed RegisteredController#eventRecorder(), inadvertently dropping the ability to record events outside a reconciliation context or targeting a resource other than context.getPrimaryResource().
    Suggested fixes:
  1. Re-introduce an unbound EventRecorder accessible via RegisteredController, ConfigurationService, or Operator.
  2. Allow passing an explicit target HasMetadata targetResource (or via EventRecord / EventRecorder#record(targetResource, ...)), rather than exclusively binding to context.getPrimaryResource().

Additional context

Our use case: We have separate controllers reconciling sub-resources. When state changes or failures occur during the reconciliation of a sub-resource, we need to publish a Kubernetes event targeting the main/parent resource so users inspecting the parent resource (kubectl describe ) have visibility into events triggered by its sub-resources.

Activity

  1. csviri commented on Nov 10, 2026

    @csviri
    Collaborator

    Hi @bertdw-1985 , thx for raising this, that is a issue with the blog, attached a PR to fix that. At the end we decided to do it this way, since the event coming from a controller bounded to the primary resource is the behavior that we would normally see, we can take a look and extend this.

  2. added this to the 5.8 milestone on Nov 10, 2026
  3. reopened this on Nov 10, 2026
  4. csviri commented on Nov 10, 2026

    @csviri
    Collaborator
  5. afalhambra-hivemq commented on Nov 11, 2026

    @afalhambra-hivemq
    Contributor

    @csviri @bertdw-1985 I'm working on this on top of next: recording events about any object, not only the primary (so a child controller can record on its parent), and recording outside of a reconciliation through the registered controller. Existing context.eventRecorder() usage stays as is. PR soon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions