apache/beam · error

err

Error message

err

What it means

beam.NewElementEncoder infers a coder for the given reflect.Type and panics on any inference error, surfacing the raw error as the panic value (message 'err'). It is a convenience API that treats coder inference failure as a non-recoverable programming error.

Source

Thrown at sdks/go/pkg/beam/coder.go:111

// encoding: encoding two equal values always yields identical byte
// sequences.
//
// Determinism is required for any coder used as a state key in a stateful
// DoFn or as the key component of a KV consumed by GroupByKey /
// GroupIntoBatches. A non-deterministic key coder would silently corrupt
// state keying, splintering state across apparently-distinct keys.
func (c Coder) IsDeterministic() bool {
	if c.coder == nil {
		return false
	}
	return c.coder.IsDeterministic()
}

// NewElementEncoder returns a new encoding function for the given type.
func NewElementEncoder(t reflect.Type) ElementEncoder {
	c, err := inferCoder(typex.New(t))
	if err != nil {
		panic(err)
	}
	return &execEncoder{enc: exec.MakeElementEncoder(c)}
}

// execEncoder wraps an exec.ElementEncoder to implement the ElementDecoder interface
// in this package.
type execEncoder struct {
	enc   exec.ElementEncoder
	coder *coder.Coder
}

func (e *execEncoder) Encode(element any, w io.Writer) error {
	return e.enc.Encode(&exec.FullValue{Elm: element}, w)
}

func (e *execEncoder) String() string {
	return e.coder.String()
}

View on GitHub (pinned to 12126d8942)

Solutions

  1. Register a custom coder for the type via beam.RegisterCoder before calling NewElementEncoder
  2. Use only supported types (primitives, slices, maps, arrays, structs of supported types, KV, etc.)
  3. Change the calling code to use TryInfer or capture the error path instead of the panicking convenience wrapper
  4. Inspect the panic value for the specific inference failure reason

Example fix

// before
enc := beam.NewElementEncoder(reflect.TypeOf(make(chan int)))
// after
typex.RegisterCoder(reflect.TypeOf(chanInt(0)), encodeChan, decodeChan)
enc := beam.NewElementEncoder(reflect.TypeOf(chanInt(0)))
Defensive patterns

Strategy: try-catch

Validate before calling

switch t.Kind() {
case reflect.Chan, reflect.Func, reflect.UnsafePointer, reflect.Interface:
	return errors.New("unsupported type for element encoder")
}

Type guard

func encodable(t reflect.Type) bool {
	switch t.Kind() {
	case reflect.Chan, reflect.Func, reflect.UnsafePointer, reflect.Interface:
		return false
	}
	return true
}

Try / catch

func safeEncoder(t reflect.Type) (enc beam.ElementEncoder, err error) {
	defer func() {
		if r := recover(); r != nil {
			err = fmt.Errorf("coder inference failed: %v", r)
		}
	}()
	return beam.NewElementEncoder(t), nil
}

Prevention

When it happens

Trigger: Passing a reflect.Type whose element type the SDK cannot infer a coder for — e.g. an unsupported container (chan, func), unregistered custom struct with unsupported fields, or interface types.

Common situations: Encoding channels, function values, or types containing them; custom types without registered coders; complex nested generics the inference rules don't cover.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/266a75150bdd0178. Report an issue: GitHub.