apache/beam · error
NewSK: keyCoder must not be nil
Error message
NewSK: keyCoder must not be nil
What it means
NewSK in sdks/go/pkg/beam/core/graph/coder/coder.go panics with "NewSK: keyCoder must not be nil" when constructing a ShardedKey coder without a key coder. A ShardedKey coder is a composite whose single component is the key's coder, mirroring KV, so nil is invalid. The panic is a fail-fast constructor contract check.
Solutions
- Build the key coder before NewSK: kc := coder.NewJ(keyType); skc := coder.NewSK(kc).
- Fix the code producing the nil key coder — check every (coder, err) return for swallowed errors.
- Add a nil assertion before the call to surface the problem with more context.
Example fix
// before
skc := coder.NewSK(nil) // panics
// after
kc := coder.NewJ(reflect.TypeOf(""))
skc := coder.NewSK(kc) Defensive patterns
Strategy: validation
Validate before calling
if kc == nil {
return nil, errors.New("key coder must be initialized before NewSK")
}
skc := coder.NewSK(kc) Type guard
func isCoderReady(c *coder.Coder) bool { return c != nil && c.T != nil } Try / catch
func newSKSafe(kc *coder.Coder) (skc *coder.Coder, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("NewSK failed: %v", r)
}
}()
return coder.NewSK(kc), nil
} Prevention
- Construct the key coder with NewJ/NewKV before calling NewSK.
- Check (coder, err) returns so nil key coders never propagate.
- Add unit tests for sharded-key coder construction paths (mirroring TestSK_IsDeterministic).
When it happens
Trigger: Calling coder.NewSK(nil) directly or via makeCoder in tests, or passing a key coder from a failed lookup that returned nil with its error ignored.
Common situations: Pipelines using sharded keys (TryCombinePerKey outputs, TestShardedKeyCoder_WireFormat) where key-coder wiring was assembled dynamically and lost initialization.
Related errors
- coder must not be nil
- window must not be nil
- array len mismatch. decoding
- coder type must be identical to node type
- could not unmarshal CoderRef from
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/0e6b9e9db7eeddab.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/graph/coder/coder.go:533
func NewCoGBK(components []*Coder) *Coder {
checkCodersNotNil(components)
return &Coder{
Kind: CoGBK,
T: typex.New(typex.CoGBKType, Types(components)...),
Components: components,
}
}
// NewSK returns a coder for ShardedKey-typed values. The component
// keyCoder encodes the user key; the ShardID is encoded as a
// length-prefixed byte string preceding it (beam:coder:sharded_key:v1).
//
// The resulting FullType root is typex.ShardedKeyType with the key's
// FullType as the single component, following the same Composite
// pattern as KV.
func NewSK(keyCoder *Coder) *Coder {
if keyCoder == nil {
panic("NewSK: keyCoder must not be nil")
}
return &Coder{
Kind: ShardedKey,
T: typex.New(typex.ShardedKeyType, keyCoder.T),
Components: []*Coder{keyCoder},
}
}
// IsSK returns true iff the coder is for a ShardedKey.
func IsSK(c *Coder) bool {
return c != nil && c.Kind == ShardedKey
}
// SkipW returns the data coder used by a WindowedValue, or returns the coder. This
// allows code to seamlessly traverse WindowedValues without additional conditional
// code.
func SkipW(c *Coder) *Coder {
if c.Kind == WindowedValue {View on GitHub (pinned to 12126d8942)