apache/beam · error

unexpected coder kind

Error message

unexpected coder kind: %v

What it means

Produced by CoderMarshaller.Add's default branch when the coder's Kind matches none of the handled cases (Custom, KV, Window, Timer, Iterable, Bool, Bytes, etc.). It signals an unsupported or unrecognized coder kind in the model marshalling switch, then wrapped with 'failed to marshal coder' context.

Solutions

  1. Print/log c.Kind to identify the unsupported kind value.
  2. Upgrade the Go Beam SDK so the marshaller recognizes the coder kind.
  3. Replace the coder with a supported built-in (bytes, KV, iterable, windowed).
  4. If custom, use coder.NewCustomCoder with valid Encode/Decode functions, which takes the Custom branch instead.
  5. Check for version mismatch between pipeline-construction SDK and the Go container/runner.

Example fix

// before
c := &coder.Coder{Kind: coder.Kind(999), T: typex.New(typex.VarIntType)}
// after
c := coder.NewI( /* int64 element */ ) // use a known constructor so Kind is valid
Defensive patterns

Strategy: type-guard

Validate before calling

switch c.Kind {
case coder.Custom, coder.KV, coder.Window, coder.Timer, coder.Iterable, coder.Bool, coder.Bytes:
    // ok
default:
    return fmt.Errorf("kind %v not marshalable", c.Kind)
}

Type guard

func hasMarshalableKind(c *coder.Coder) bool {
    k := c.Kind
    return k == coder.Custom || k == coder.KV || k == coder.Window || k == coder.Timer || k == coder.Iterable || k == coder.Bool || k == coder.Bytes
}

Try / catch

id, err := b.Add(c)
if err != nil && strings.Contains(err.Error(), "unexpected coder kind") {
    return "", fmt.Errorf("coder %v uses unsupported kind %v; upgrade SDK or replace coder", c, c.Kind)
}

Prevention

When it happens

Trigger: Add/AddMulti receives a *coder.Coder whose Kind is not implemented by the marshaller — typically a hand-constructed coder or one produced by a newer/other SDK with a kind this Go version does not know.

Common situations: Version skew between Beam SDKs in cross-language pipelines; custom coders registered in one SDK but not Go; building coder.Coder values manually with an invalid zero-value Kind.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/graphx/coder.go:582

		comp = append(comp, ids...)

		id, err := b.AddWindowCoder(c.Window)
		if err != nil {
			return "", errors.Wrapf(err, "failed to marshal window coder %v", c)
		}
		comp = append(comp, id)

		return b.internBuiltInCoder(urnTimerCoder, comp...), nil

	case coder.Iterable:
		comp, err := b.AddMulti(c.Components)
		if err != nil {
			return "", errors.Wrapf(err, "failed to marshal iterable coder %v", c)
		}
		return b.internBuiltInCoder(urnIterableCoder, comp...), nil

	default:
		err := errors.Errorf("unexpected coder kind: %v", c.Kind)
		return "", errors.WithContextf(err, "failed to marshal coder %v", c)
	}
}

// AddMulti adds the given coders to the set and returns their ids. Idempotent.
func (b *CoderMarshaller) AddMulti(list []*coder.Coder) ([]string, error) {
	var ids []string
	for _, c := range list {
		if id, err := b.Add(c); err != nil {
			return nil, errors.Wrapf(err, "failed to marshal the coder %v.", c)
		} else {
			ids = append(ids, id)
		}
	}
	return ids, nil
}

// AddWindowCoder adds a window coder.

View on GitHub (pinned to 12126d8942)