apache/beam · critical
Creating CustomCoder for type failed
Error message
Creating %v CustomCoder for type %v failed
What it means
Inside the registry's lazy per-type factory, NewCustomCoder is re-invoked with the concrete type rt; if it fails the code panics with "Creating %v CustomCoder for type %v failed". The source comment notes this should be unreachable after Register-time validation, so it signals an internal invariant violation — usually the concrete type rt differs from the registered type in a way validation did not anticipate.
Solutions
- Register the coder for the exact concrete type being looked up
- Treat as a Beam bug: verify the reproduction and file/check an issue
- Verify no duplicate registrations with mismatched funcs for related types
Defensive patterns
Strategy: try-catch
Try / catch
defer func() {
if r := recover(); r != nil {
if strings.Contains(fmt.Sprint(r), "CustomCoder for type") {
log.Fatalf("registry invariant violated: %v", r)
}
panic(r)
}
}() Prevention
- Register coders for the exact concrete type that will be looked up
- Avoid duplicate/conflicting registrations for related types
- Report reproducible hits to Beam — this path is expected unreachable
When it happens
Trigger: Looking up a coder by concrete type rt where re-creating the CustomCoder with rt fails despite passing validation at registration time.
Common situations: Registering for a base/interface type then looking up with a related concrete type where the encode/decode funcs no longer type-check; Beam-internal bugs after version upgrades.
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
- RegisterCoder failed for type
- broken invariant: idsFound map is nil, but idsRequired map…
- couldn't decode characteristic for variant
- empty slice passed as an argument to trigger.AfterAny()
- err
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/1b937e7574d6d6b4.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/graph/coder/registry.go:75
for i, iT := range interfaceOrdering {
if iT == t {
index = i
break
}
}
interfaceOrdering = append(interfaceOrdering[:index], interfaceOrdering[index+1:]...)
}
// Either way, always append.
interfaceOrdering = append(interfaceOrdering, t)
}
name := t.String() // Use the real type names for coders.
coderRegistry[t] = func(rt reflect.Type) *CustomCoder {
// We need to provide the concrete type, so that coders that use
// the reflect.Type have the proper instance.
cc, err := NewCustomCoder(name, rt, enc, dec)
if err != nil {
// An error on look up shouldn't happen after the validation.
panic(errors.Wrapf(err, "Creating %v CustomCoder for type %v failed", name, rt))
}
return cc
}
}
// RegisterDeterministicCoderWithFuncs is like RegisterDeterministicCoder
// but accepts pre-wrapped reflectx.Func values (typically built via
// reflectx.MakeFuncWithName) so the caller controls the function name
// used during cross-worker serialization. This is required for
// closures inside Go generic functions where different type
// instantiations produce closures with the same compiler name.
func RegisterDeterministicCoderWithFuncs(t reflect.Type, encFn, decFn *funcx.Fn) {
name := t.String()
coderRegistry[t] = func(rt reflect.Type) *CustomCoder {
return NewCustomCoderWithFuncs(name, rt, encFn, decFn)
}
deterministicRegistry[t] = true
}View on GitHub (pinned to 12126d8942)