apache/seatunnel · error · SeaTunnelEngineException

The state must be end state from ExecutionService, can not b

Error message

The state must be end state from ExecutionService, can not be ${executionState}

What it means

updateStateByExecutionService is the callback for ExecutionService task-completion notifications, which are only expected to deliver end states (FINISHED, FAILED, CANCELED). Receiving a non-end state means the internal contract between ExecutionService and PhysicalVertex is broken, so a SeaTunnelEngineException is thrown immediately.

Source

Thrown at seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/dag/physical/PhysicalVertex.java:535

                                "Set %s state %s to Imap failed, skip.",
                                getTaskFullName(), ExecutionState.CREATED));
            }
            this.currExecutionState = ExecutionState.CREATED;
            log.info(String.format("%s turn to state %s.", taskFullName, ExecutionState.CREATED));
        }
    }

    public void reset() {
        resetExecutionState();
    }

    public String getTaskFullName() {
        return taskFullName;
    }

    public void updateStateByExecutionService(TaskExecutionState taskExecutionState) {
        if (!taskExecutionState.getExecutionState().isEndState()) {
            throw new SeaTunnelEngineException(
                    String.format(
                            "The state must be end state from ExecutionService, can not be %s",
                            taskExecutionState.getExecutionState()));
        }
        errorByPhysicalVertex.compareAndSet(null, taskExecutionState.getThrowableMsg());
        updateTaskState(taskExecutionState.getExecutionState());
    }

    public synchronized void forceStop() {
        ExecutionState executionState = getExecutionState();
        if (executionState == null || executionState.isEndState()) {
            return;
        }
        noticeTaskExecutionServiceCancel();
        if (!taskFuture.isDone()) {
            updateTaskState(ExecutionState.CANCELED);
        }
    }

View on GitHub (pinned to cf67b549a7)

Solutions

  1. Verify all engine modules run the same SeaTunnel version (no mixed jars)
  2. Ensure ExecutionService only notifies the vertex of terminal task states
  3. Check for custom patches/modified ExecutionService code and revert to upstream
  4. Capture logs of the offending TaskExecutionState and report the engine bug

Example fix

// before
vertex.updateStateByExecutionService(new TaskExecutionState(loc, ExecutionState.RUNNING, null));
// after
if (state.getExecutionState().isEndState()) {
    vertex.updateStateByExecutionService(state);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!taskExecutionState.getExecutionState().isEndState()) { return; // do not forward to updateStateByExecutionService }

Type guard

boolean isTerminalTaskState(TaskExecutionState s) { return s.getExecutionState().isEndState(); }

Try / catch

try { vertex.updateStateByExecutionState(tes); } catch (SeaTunnelEngineException e) { if (e.getMessage().contains("must be end state from ExecutionService")) { log.error("contract violation in task notification", e); } else { throw e; } }

Prevention

When it happens

Trigger: ExecutionService invokes updateStateByExecutionService with a TaskExecutionState whose execution state is RUNNING, CREATED, FAILING, etc.; an engine bug or version mismatch delivering intermediate states through this channel.

Common situations: Custom engine modifications that forward intermediate task states to the plan; mixed engine jar versions after an upgrade; bugs in task lifecycle reporting during failover.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of apache/seatunnel@cf67b549a7 (2026-09-10). Data as JSON: /api/errors/6b27c889ed2c894c. Report an issue: GitHub.