apache/beam · error
unknown ShutdownMode
Error message
unknown ShutdownMode: %v
What it means
beam.Init() takes over main for Beam workers and installs an exit hook that decides whether the process terminates hard (os.Exit) or returns control. Only ShutdownMode Terminate and Return are defined; any other value is a programming error, so the code panics with the offending value.
Solutions
- Set ShutdownMode only to init.Terminate or init.Return.
- Remove any custom assignment if you don't need to change shutdown behavior; keep the default.
- Audit for concurrent writes to ShutdownMode; make the assignment once at startup.
Example fix
// before init.ShutdownMode = init.ShutdownMode(3) // after init.ShutdownMode = init.Return // or init.Terminate
Defensive patterns
Strategy: validation
Validate before calling
if init.ShutdownMode != init.Terminate && init.ShutdownMode != init.Return {
panic("ShutdownMode must be init.Terminate or init.Return")
} Try / catch
defer func() { if r := recover(); r != nil { log.Fatalf("shutdown mode error: %v", r) } }() Prevention
- Only assign the two exported constants to ShutdownMode
- Never read ShutdownMode values from unvalidated config
- Set ShutdownMode once, early, and treat it as immutable
When it happens
Trigger: Assigning any value to the harness init.ShutdownMode package variable other than init.Terminate or init.Return before/while the deferred exit hook runs in the path guarded by the harness Main.
Common situations: Custom worker code setting ShutdownMode to an out-of-range integer or an unexported/foreign type; copy-paste code importing the wrong ShutdownMode constant; concurrent code mutating ShutdownMode mid-run.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- empty port
- AfterProcessingTime trigger set without a delay or…
- At least one subtrigger required for composite triggers.
- attempted to add namespace to missing coder id
- attempted to add namespace to missing windowing strategy id
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/de52dc2d030fe8d8.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/runtime/harness/init/init.go:138
experiments = strings.Split(e, ",")
}
// TODO(zechenj18) 2023-12-07: Remove once the data sampling URN is properly sent in via the capabilities
if slices.Contains(experiments, "enable_data_sampling") {
runnerCapabilities = append(runnerCapabilities, graphx.URNDataSampling)
}
}
defer func() {
if r := recover(); r != nil {
fmt.Fprintf(os.Stderr, "Worker panic: %v\n", r)
debug.PrintStack()
switch ShutdownMode {
case Terminate:
os.Exit(2)
case Return:
return
default:
panic(fmt.Sprintf("unknown ShutdownMode: %v", ShutdownMode))
}
}
}()
// Since Init() is hijacking main, it's appropriate to do as main
// does, and establish the background context here.
// We produce a cancelFn here so runs in Loopback mode and similar can clean up
// any leftover goroutines.
ctx, cancelFn := context.WithCancel(context.Background())
defer cancelFn()
ctx = grpcx.WriteWorkerID(ctx, *id)
memLimit := memoryLimit()
if err := syscallx.SetProcessMemoryCeiling(memLimit, memLimit); err != nil && err != syscallx.ErrUnsupported {
fmt.Println("Error Setting Rlimit ", err)
}
options := harness.Options{
StatusEndpoint: statusEndpoint,View on GitHub (pinned to 12126d8942)