apache/iceberg · error · IllegalArgumentException

Invalid operator event type:

Error message

Invalid operator event type: 

What it means

TriggerManagerOperator.handleOperatorEvent is the per-subtask OperatorEvent handler and only accepts LockReleaseEvent. Any other OperatorEvent type throws this IllegalArgumentException. The two known callers are tests (testStateRestore, testLockCheckDelay), meaning production code should only ever deliver LockReleaseEvent here.

Source

Thrown at flink/v2.2/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. Ensure LockReleaseEvent is the only event sent to the TriggerManager operator's event gateway.
  2. Send LockRegisterEvent to TriggerManagerCoordinator (coordinator gateway), not to subtask operators.
  3. Match Iceberg versions between checkpoint creation and restore.
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(event instanceof LockReleaseEvent)) {
  LOG.warn("Ignoring unexpected event at TriggerManagerOperator: {}", event.getClass());
  return;
}

Type guard

boolean isLockRelease(OperatorEvent e) { return e instanceof LockReleaseEvent; }

Try / catch

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

Prevention

When it happens

Trigger: An OperatorEvent that is not LockReleaseEvent is delivered to the TriggerManager operator's gateway — e.g. a LockRegisterEvent sent to subtasks instead of the coordinator, or events from a different Iceberg version after restore.

Common situations: Custom operators/tests sending wrong event types, or cross-version savepoint restores where the event class hierarchy changed.

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/fe99a96908900c5d. Report an issue: GitHub.