apache/beam · critical
panic
Error message
panic: %v %s
What it means
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.
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.
Example fix
// before
func (fn *parseFn) ProcessElement(ctx context.Context, line string, emit func(Row)) {
fields := strings.Split(line, ",")
emit(Row{ID: fields[1]}) // panics if line has no comma
}
// after
func (fn *parseFn) ProcessElement(ctx context.Context, line string, emit func(Row)) {
fields := strings.Split(line, ",")
if len(fields) < 2 {
return // skip or log malformed line instead of panicking
}
emit(Row{ID: fields[1]})
} Defensive patterns
Strategy: try-catch
Try / catch
// The SDK already recovers the panic; handle the returned error in your pipeline:
if err := beam.RunWithEnvironment(ctx, p); err != nil {
var dErr *exec.doFnError
if errors.As(err, &dErr) {
log.Printf("DoFn failed: %v", dErr)
} else if strings.Contains(err.Error(), "panic:") {
log.Printf("panic in DoFn: %v", err)
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Invalid signature for FinishBundle
- Invalid signature for StartBundle
- invoker: has > 5 return values, which is not permitted
- panic(err)
- Unable to infer the types of FinishBundle
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/998637d3ab931e8c.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/runtime/exec/util.go:58
uid UnitID
pid string
}
func (e *doFnError) Error() string {
return fmt.Sprintf("DoFn[UID:%v, PID:%v, Name: %v] failed:\n%v", e.uid, e.pid, e.doFn, e.err)
}
// callNoPanic calls the given function and catches any panic.
func callNoPanic(ctx context.Context, fn func(context.Context) error) (err error) {
defer func() {
if r := recover(); r != nil {
// Check if the panic value is from a failed DoFn, and return it without a panic trace.
if e, ok := r.(*doFnError); ok {
err = e
} else {
// Top level error is the panic itself, but also include the stack trace as the original error.
// Higher levels can then add appropriate context without getting pushed down by the stack trace.
err = errors.SetTopLevelMsgf(errors.Errorf("panic: %v %s", r, debug.Stack()), "panic: %v", r)
}
}
}()
return fn(ctx)
}
// MultiStartBundle calls StartBundle on multiple nodes. Convenience function.
func MultiStartBundle(ctx context.Context, id string, data DataContext, list ...Node) error {
for _, n := range list {
if err := n.StartBundle(ctx, id, data); err != nil {
return err
}
}
return nil
}
// MultiFinishBundle calls FinishBundle on multiple nodes. Convenience function.
func MultiFinishBundle(ctx context.Context, list ...Node) error {View on GitHub (pinned to 12126d8942)