apache/iceberg · error · IllegalArgumentException

Invalid operator event type: <event.getClass().getCanonicalN

Error message

Invalid operator event type: <event.getClass().getCanonicalName()>

What it means

TriggerManagerOperator.handleOperatorEvent accepts only LockReleaseEvent (the lock-removed notification from the maintenance job). Any other OperatorEvent type is rejected with an IllegalArgumentException identifying the class. This indicates the operator received an event outside its expected protocol.

Source

Thrown at flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/maintenance/operator/TriggerManagerOperator.java:219

      nextEvaluationTimeState.add(nextEvaluationTime);
    }

    accumulatedChangesState.update(accumulatedChanges);
    lastTriggerTimesState.update(lastTriggerTimes);
    LOG.info(
        "Storing state: nextEvaluationTime {}, accumulatedChanges {}, lastTriggerTimes {}",
        nextEvaluationTime,
        accumulatedChanges,
        lastTriggerTimes);
  }

  @Override
  public void handleOperatorEvent(OperatorEvent event) {
    if (event instanceof LockReleaseEvent) {
      LOG.info("Received lock released event: {}", event);
      handleLockRelease((LockReleaseEvent) event);
    } else {
      throw new IllegalArgumentException(
          "Invalid operator event type: " + event.getClass().getCanonicalName());
    }
  }

  @Override
  public void processElement(StreamRecord<TableChange> streamRecord) throws Exception {
    TableChange change = streamRecord.getValue();
    accumulatedChanges.forEach(tableChange -> tableChange.merge(change));
    if (nextEvaluationTime == null) {
      checkAndFire(getProcessingTimeService());
    } else {
      LOG.info(
          "Trigger manager rate limiter triggered current: {}, next: {}, accumulated changes: {},{}",
          getProcessingTimeService().getCurrentProcessingTime(),
          nextEvaluationTime,
          accumulatedChanges,
          maintenanceTaskNames);
      rateLimiterTriggeredCounter.inc();

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Send only LockReleaseEvent to TriggerManagerOperator; LockRegisterEvent belongs on the coordinator side.
  2. Review the event-sending code path and the OperatorEventGateway used.
  3. If a new event type is needed, add an instanceof branch in handleOperatorEvent.

Example fix

// before
operator.handleOperatorEvent(new LockRegisterEvent(factory, id));
// after
operator.handleOperatorEvent(new LockReleaseEvent(taskId));
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(event instanceof LockReleaseEvent)) { throw new IllegalStateException("TriggerManagerOperator only accepts LockReleaseEvent"); }

Type guard

if (event instanceof LockReleaseEvent release) { /* release handling */ }

Try / catch

try { operator.handleOperatorEvent(event); } catch (IllegalArgumentException e) { LOG.error("Unexpected operator event for trigger manager", e); }

Prevention

When it happens

Trigger: Calling handleOperatorEvent on a TriggerManagerOperator with anything other than a LockReleaseEvent (e.g. a LockRegisterEvent or custom event). Reached in tests testStateRestore/testLockCheckDelay and via Flink's operator event pathway.

Common situations: Custom code or tests sending wrong event types to the trigger manager operator; wiring changes where register events are mistakenly delivered to the operator instead of the coordinator.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/b77f3a02762afc2f. Report an issue: GitHub.