{"record":{"id":"7e67cd78f88a6cdb","repo":"apache/beam","slug":"v","errorCode":null,"errorMessage":"%v","messagePattern":"%v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/runners/prism/internal/stage.go","lineNumber":419,"sourceCode":"// buildDescriptor constructs a ProcessBundleDescriptor for bundles of this stage.\n//\n// Requirements:\n// * The set of inputs to the stage only include one parallel input.\n// * The side input pcollections are fully qualified with global pcollection ID, ingesting transform, and local inputID.\n// * The outputs are fully qualified with global PCollectionID, producing transform, and local outputID.\n//\n// It assumes that the side inputs are not sourced from PCollections generated by any transform in this stage.\n//\n// Because we need the local ids for routing the sources/sinks information.\nfunc buildDescriptor(stg *stage, comps *pipepb.Components, wk *worker.W, em *engine.ElementManager) (err error) {\n\t// Catch construction time panics and produce them as errors out.\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\tswitch rt := r.(type) {\n\t\t\tcase error:\n\t\t\t\terr = rt\n\t\t\tdefault:\n\t\t\t\terr = fmt.Errorf(\"%v\", r)\n\t\t\t}\n\t\t}\n\t}()\n\t// Assume stage has an indicated primary input\n\n\tcoders := map[string]*pipepb.Coder{}\n\ttransforms := map[string]*pipepb.PTransform{}\n\tpcollections := map[string]*pipepb.PCollection{}\n\n\tclonePColToBundle := func(pid string) *pipepb.PCollection {\n\t\tcol := proto.Clone(comps.GetPcollections()[pid]).(*pipepb.PCollection)\n\t\tpcollections[pid] = col\n\t\treturn col\n\t}\n\n\t// Update coders for Stateful transforms.\n\tfor _, tid := range stg.transforms {\n\t\tt := comps.GetTransforms()[tid]","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/runners/prism/internal/stage.go#L401-L437","documentation":"This is a recover() wrapper that converts a panic from bundle descriptor building into a normal error. If the recovered value is already an error it is used as-is; any other panic value is wrapped via fmt.Errorf(\"%v\", r).","triggerScenarios":"Any panic during descriptor construction — typically coder lookups or map indexing on missing/nil coders while assembling the bundle's process-bundle descriptor.","commonSituations":"Runner bugs handling unusual coder combinations (e.g. cross-language or windowed coders) that trigger nil map access or index panics.","solutions":["Read the converted error's message to identify the panicking value","Check the stage's coder definitions in the pipeline proto for nils or missing references","Retry with a simpler pipeline to isolate the coder causing the panic","File a Beam issue with logs if it's a prism bug"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := buildDescriptor(...); err != nil {\n    slog.Error(\"descriptor build recovered panic\", \"err\", err)\n    return err\n}","preventionTips":["Audit coder references for nils/missing definitions in pipeline protos","Test with cross-language coders before production","Keep runner updated for coder handling fixes"],"tags":["go","panic","beam","coder"],"backgroundTag":"recovered-panic","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"}