{"record":{"id":"0d44b5b9e424e1d8","repo":"apache/beam","slug":"unexpected-job-update-v","errorCode":null,"errorMessage":"unexpected job update: %v","messagePattern":"unexpected job update: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/runners/universal/runnerlib/job.go","lineNumber":163,"sourceCode":"\t\t\t}\n\t\t\tif resp.GetMessageId() != \"\" {\n\t\t\t\tfmt.Fprintf(&b, \"(id=%v)\", resp.GetMessageId())\n\t\t\t}\n\t\t\tb.WriteString(resp.GetMessageText())\n\t\t\ttext := b.String()\n\n\t\t\tlog.Output(ctx, messageSeverity(resp.GetImportance()), 1, text)\n\n\t\t\tif resp.GetImportance() >= jobpb.JobMessage_JOB_MESSAGE_ERROR {\n\t\t\t\terrReceived = true\n\t\t\t\tmostRecentError = resp.GetMessageText()\n\n\t\t\t\tif jobFailed {\n\t\t\t\t\treturn errors.Errorf(\"job %v failed:\\n%w\", jobID, errors.New(mostRecentError))\n\t\t\t\t}\n\t\t\t}\n\n\t\tdefault:\n\t\t\treturn errors.Errorf(\"unexpected job update: %v\", msg.String())\n\t\t}\n\t}\n}\n\nfunc messageSeverity(importance jobpb.JobMessage_MessageImportance) log.Severity {\n\tswitch importance {\n\tcase jobpb.JobMessage_JOB_MESSAGE_ERROR:\n\t\treturn log.SevError\n\tcase jobpb.JobMessage_JOB_MESSAGE_WARNING:\n\t\treturn log.SevWarn\n\tcase jobpb.JobMessage_JOB_MESSAGE_BASIC:\n\t\treturn log.SevInfo\n\tcase jobpb.JobMessage_JOB_MESSAGE_DEBUG, jobpb.JobMessage_JOB_MESSAGE_DETAILED:\n\t\treturn log.SevDebug\n\tdefault:\n\t\treturn log.SevUnspecified\n\t}","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/runners/universal/runnerlib/job.go#L145-L181","documentation":"WaitForCompletion processes a stream of job update messages of several known kinds (messages, state changes, metrics). If a message arrives whose type does not match any handled case, the universal runner aborts with 'unexpected job update: %v', including the protobuf message's String() form. It indicates a protocol mismatch between client and job service.","triggerScenarios":"Streaming GetJobEvents/GetMessages responses whose oneof variant is not among the cases handled in WaitForCompletion — typically from a newer/older runner server version speaking a slightly different Job API.","commonSituations":"Version skew between the Beam Go SDK and the remote runner (e.g. Flink/Spanner portable job server updated independently); proxies injecting unexpected message types.","solutions":["Align the Beam Go SDK version with the runner/job-service version","Log the full msg.String() content shown in the error to identify the unknown message type","Pin container/runner images to compatible Beam versions","If the message is benign, upgrade Beam — newer client versions handle more update kinds"],"exampleFix":"// before\ndefault:\n\treturn errors.Errorf(\"unexpected job update: %v\", msg.String())\n// after\ndefault:\n\tlog.Printf(\"ignoring unknown job update: %v\", msg.String())\n\t// or upgrade the SDK to match the job service version\n\treturn errors.Errorf(\"unexpected job update: %v\", msg.String())","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := runner.WaitForCompletion(ctx, conn, jobID, deadline, printer); err != nil {\n\tif strings.Contains(err.Error(), \"unexpected job update\") {\n\t\tlog.Printf(\"protocol mismatch with job service: %v\", err)\n\t}\n\treturn err\n}","preventionTips":["Pin the Go SDK version to the runner's Beam version","Upgrade the SDK if the runner was updated to a newer Beam release","Log full message contents when introducing new runner backends"],"tags":["go","beam","universal-runner","protocol"],"backgroundTag":"unexpected-response-shape","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}