{"record":{"id":"998637d3ab931e8c","repo":"apache/beam","slug":"panic-v-s","errorCode":null,"errorMessage":"panic: %v %s","messagePattern":"panic: (.+?) (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"sdks/go/pkg/beam/core/runtime/exec/util.go","lineNumber":58,"sourceCode":"\tuid  UnitID\n\tpid  string\n}\n\nfunc (e *doFnError) Error() string {\n\treturn fmt.Sprintf(\"DoFn[UID:%v, PID:%v, Name: %v] failed:\\n%v\", e.uid, e.pid, e.doFn, e.err)\n}\n\n// callNoPanic calls the given function and catches any panic.\nfunc callNoPanic(ctx context.Context, fn func(context.Context) error) (err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\t// Check if the panic value is from a failed DoFn, and return it without a panic trace.\n\t\t\tif e, ok := r.(*doFnError); ok {\n\t\t\t\terr = e\n\t\t\t} else {\n\t\t\t\t// Top level error is the panic itself, but also include the stack trace as the original error.\n\t\t\t\t// Higher levels can then add appropriate context without getting pushed down by the stack trace.\n\t\t\t\terr = errors.SetTopLevelMsgf(errors.Errorf(\"panic: %v %s\", r, debug.Stack()), \"panic: %v\", r)\n\t\t\t}\n\t\t}\n\t}()\n\treturn fn(ctx)\n}\n\n// MultiStartBundle calls StartBundle on multiple nodes. Convenience function.\nfunc MultiStartBundle(ctx context.Context, id string, data DataContext, list ...Node) error {\n\tfor _, n := range list {\n\t\tif err := n.StartBundle(ctx, id, data); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\n// MultiFinishBundle calls FinishBundle on multiple nodes. Convenience function.\nfunc MultiFinishBundle(ctx context.Context, list ...Node) error {","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/runtime/exec/util.go#L40-L76","documentation":"The Beam Go SDK's invoke helper (exec/util.go) recovers a panic from user code (e.g. a DoFn) and converts it into an error. If the panic value is not already a *doFnError, it wraps the panic value plus debug.Stack() into a top-level error message \"panic: %v %s\". It exists so a crashing DoFn surfaces as a pipeline error with the panic value prominent and the stack trace preserved as the original error.","triggerScenarios":"Any panic (nil pointer dereference, index out of range, explicit panic()) raised inside a DoFn's ProcessElement, StartBundle, FinishBundle, or a wrapped function executed via the exec framework's invoke path.","commonSituations":"User DoFn code dereferences a nil map/pointer, divides by zero, indexes a slice out of bounds, or panics inside a custom emitter or side-input callback during pipeline execution on DirectRunner or Dataflow.","solutions":["Read the panic value in 'panic: <value>' and fix the DoFn code at the stack-trace location included in the error.","Add nil/empty checks in the DoFn before dereferencing elements, maps, or side inputs.","Recover and translate expected failure modes into returned errors inside the DoFn instead of panicking.","Log incoming elements that trigger the panic and add validation/reject handling for malformed input."],"exampleFix":"// before\nfunc (fn *parseFn) ProcessElement(ctx context.Context, line string, emit func(Row)) {\n    fields := strings.Split(line, \",\")\n    emit(Row{ID: fields[1]}) // panics if line has no comma\n}\n// after\nfunc (fn *parseFn) ProcessElement(ctx context.Context, line string, emit func(Row)) {\n    fields := strings.Split(line, \",\")\n    if len(fields) < 2 {\n        return // skip or log malformed line instead of panicking\n    }\n    emit(Row{ID: fields[1]})\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// The SDK already recovers the panic; handle the returned error in your pipeline:\nif err := beam.RunWithEnvironment(ctx, p); err != nil {\n    var dErr *exec.doFnError\n    if errors.As(err, &dErr) {\n        log.Printf(\"DoFn failed: %v\", dErr)\n    } else if strings.Contains(err.Error(), \"panic:\") {\n        log.Printf(\"panic in DoFn: %v\", err)\n    }\n}","preventionTips":["Validate and sanitize inputs at the start of every ProcessElement.","Check slices/maps for nil and length before indexing.","Recover expected failure modes in DoFns and return errors instead of panicking.","Test DoFns with malformed/empty input data before running at scale."],"tags":["go","panic","dofn","pipeline-execution"],"backgroundTag":"internal-invariant-violation","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}