{"record":{"id":"aed33cc9ee3c0f24","repo":"apache/beam","slug":"job-v-failed-v","errorCode":null,"errorMessage":"job %v failed:\n%v","messagePattern":"job (.+?) failed:\n(.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/runners/universal/runnerlib/job.go","lineNumber":115,"sourceCode":"\n// WaitForCompletion monitors the given job until completion. It logs any messages\n// and state changes received.\nfunc WaitForCompletion(ctx context.Context, client jobpb.JobServiceClient, jobID string) error {\n\tstream, err := client.GetMessageStream(ctx, &jobpb.JobMessagesRequest{JobId: jobID})\n\tif err != nil {\n\t\treturn errors.Wrap(err, \"failed to get job stream\")\n\t}\n\n\tmostRecentError := \"<no error received>\"\n\tvar errReceived, jobFailed bool\n\n\tfor {\n\t\tmsg, err := stream.Recv()\n\t\tif err != nil {\n\t\t\tif err == io.EOF {\n\t\t\t\tif jobFailed {\n\t\t\t\t\t// Connection finished, so time to exit, produce what we have.\n\t\t\t\t\treturn errors.Errorf(\"job %v failed:\\n%v\", jobID, mostRecentError)\n\t\t\t\t}\n\t\t\t\treturn nil\n\t\t\t}\n\t\t\treturn err\n\t\t}\n\n\t\tswitch {\n\t\tcase msg.GetStateResponse() != nil:\n\t\t\tresp := msg.GetStateResponse()\n\n\t\t\tlog.Infof(ctx, \"Job[%v] state: %v\", jobID, resp.GetState().String())\n\n\t\t\tswitch resp.State {\n\t\t\tcase jobpb.JobState_DONE, jobpb.JobState_CANCELLED:\n\t\t\t\treturn nil\n\t\t\tcase jobpb.JobState_FAILED:\n\t\t\t\tjobFailed = true\n\t\t\t\tif errReceived {","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/runners/universal/runnerlib/job.go#L97-L133","documentation":"While streaming job messages, WaitForCompletion records the most recent error and whether the job entered a failed state. When the stream ends (io.EOF) and the job had failed, it returns this error containing the job id and the most recent error message reported by the runner. This is the standard way a remote job's failure surfaces to the pipeline author.","triggerScenarios":"The message stream closes with io.EOF after the runner reported the job FAILED; WaitForCompletion returns errors.Errorf(\"job %v failed:\\n%v\", jobID, mostRecentError).","commonSituations":"User code in a DoFn panicked or errored during execution; worker crashed or OOMed; runner-side infrastructure failure; pipeline graph rejected at runtime.","solutions":["Read the %v detail (mostRecentError) — it usually names the failing step and root exception.","Inspect full worker logs via the runner's UI or job logs endpoint using the job id.","Fix the user code / resource issue that caused the step to fail (null pointers, OOM, hot keys).","Resubmit the pipeline once the cause is addressed."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := beam.Run(ctx, runner, p); err != nil {\n    var jobErr interface{ Error() string }\n    if errors.As(err, &jobErr) && strings.Contains(jobErr.Error(), \"failed:\") {\n        // parse the job id and embedded runner error, then fetch full logs\n    }\n}","preventionTips":["Add defensive error handling in DoFns so transient data issues don't fail the job.","Watch worker memory/CPU (OOM and hot keys are common job killers).","Dry-run pipelines on the direct runner with sample data before remote submission.","Correlate the job id in the message with the runner UI's log viewer for the full stack trace."],"tags":["go","beam","job-failure","runner"],"backgroundTag":"job-execution-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}