apache/beam · error · Error
Job finished in state
Error message
Job finished in state ${JobState_Enum[finalState]} What it means
Runner.run() awaits runAsync() then waitUntilFinish(); if the job terminates in any state other than DONE (e.g. FAILED, CANCELLED, UNKNOWN), it throws 'Job finished in state <STATE>'. The message names the JobState_Enum numeric value's key so developers can see which terminal state the job reached. It indicates the pipeline ran but did not complete successfully.
Solutions
- Inspect job logs on the runner service to find the root cause of the non-DONE state.
- Catch the error and check the returned PipelineResult/job state for retryable outcomes before re-submitting.
- Fix the pipeline error (bad input, OOM, missing resources) that caused the job to fail.
Example fix
// before
await runner.run(pipeline, options);
// after
try {
await runner.run(pipeline, options);
} catch (e) {
console.error("Pipeline did not finish in DONE state:", e.message);
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Validate pipeline options (project, region, tempLocation) before submitting
class MyFn extends DoFn {}
await runner.runAsync(pipeline, options); // prefer runAsync + explicit waitUntilFinish for state control Type guard
function isDone(state: JobState_Enum) { return state === JobState_Enum.DONE; } Try / catch
try {
await runner.run(pipeline, options);
} catch (e) {
if (e.message.startsWith("Job finished in state")) {
console.error("Pipeline job failed:", e.message);
// inspect service logs before retrying
} else throw e;
} Prevention
- Check job logs on the runner service after any non-DONE state
- Validate options (project, region, quotas) before submission
- Use runAsync + waitUntilFinish for finer state handling
- Implement retry with backoff for transient infrastructure failures
When it happens
Trigger: Calling runner.run(pipeline, options) when the submitted job ends in a non-DONE state — e.g. the job fails on the remote service, is cancelled, or times out.
Common situations: Worker crashes on a Dataflow/Flink job, bad pipeline logic causing runtime failure, job cancelled by a user or platform policy, quota or infrastructure failures.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Job finished in state
- A cannot be expanded
- Attempted to invoke timer
- Blocking computation failed. State
- can't get data to render
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/ce2157182c6f3249.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/typescript/src/apache_beam/runners/runner.ts:110
export abstract class Runner {
/**
* Runs the transform.
*
* Resolves to an instance of PipelineResult when the pipeline completes.
* Use runAsync() to execute the pipeline in the background.
*
* @param pipeline
* @returns A PipelineResult
*/
async run(
pipeline: (root: Root) => PValue<any> | Promise<PValue<any>>,
options?: PipelineOptions,
): Promise<PipelineResult> {
const pipelineResult = await this.runAsync(pipeline, options);
const finalState = await pipelineResult.waitUntilFinish();
if (finalState != JobState_Enum.DONE) {
// TODO: Grab the last/most severe error message?
throw new Error("Job finished in state " + JobState_Enum[finalState]);
}
return pipelineResult;
}
/**
* runAsync() is the asynchronous version of run(), does not wait until
* pipeline finishes. Use the returned PipelineResult to query job
* status.
*/
async runAsync(
pipeline: (root: Root) => PValue<any> | Promise<PValue<any>>,
options?: PipelineOptions,
): Promise<PipelineResult> {
const p = new Pipeline();
await pipeline(new Root(p));
return this.runPipeline(p.getProto());
}
View on GitHub (pinned to 12126d8942)