apache/beam · error

bad type

Error message

bad type

What it means

decodeFn fails to decode the dynamic DoFn's receiver type from the encoded type descriptor (decodeType on u.Dynfn.Type), wrapped as "bad type". The type referenced in the pipeline proto cannot be reconstructed in the worker's runtime type registry.

Solutions

  1. Register the receiver type via runtime.RegisterType in a package imported by the worker.
  2. Rebuild the worker/container from the same code revision as the pipeline submission.
  3. Verify with runtime.LookupType(runtime.TypeKey(...)) in the worker that the type resolves.
  4. Align Beam Go SDK versions between submitter and worker image.

Example fix

// before
// worker: type not registered anywhere

// after
// package imported by worker main
func init() { runtime.RegisterType(reflect.TypeOf(myFn{})) }
Defensive patterns

Strategy: validation

Validate before calling

k, _ := runtime.TypeKey(reflectx.SkipPtr(reflect.TypeOf(myFn{})))
if _, ok := runtime.LookupType(k); !ok {
    runtime.RegisterType(reflect.TypeOf(myFn{}))
}

Type guard

func typeResolvable(t reflect.Type) bool {
    k, ok := runtime.TypeKey(reflectx.SkipPtr(t))
    if !ok { return false }
    _, ok = runtime.LookupType(k)
    return ok
}

Prevention

When it happens

Trigger: DecodeMultiEdge decoding a DynFn whose encoded Type refers to a type not registered/lookup-able in the worker process.

Common situations: Type registered only in the driver; type renamed or moved between submit and run; worker container built from different code than the submitter.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/core/runtime/graphx/serialize.go:279

		}
		return &v1pb.Fn{Type: typ, Opt: string(data)}, nil

	default:
		return nil, errors.Errorf("failed to encode DoFn %v, missing fn", u)
	}
}

func decodeFn(u *v1pb.Fn) (*graph.Fn, error) {
	if u.Dynfn != nil {
		gen, err := runtime.ResolveFunction(u.Dynfn.Gen, genFnType)
		if err != nil {
			wrapped := errors.Wrapf(err, "bad symbol %v", u.Dynfn.Gen)
			return nil, errors.WithContextf(wrapped, "decoding dynamic DoFn %v", u)
		}

		t, err := decodeType(u.Dynfn.Type)
		if err != nil {
			wrapped := errors.Wrap(err, "bad type")
			return nil, errors.WithContextf(wrapped, "failed to decode dynamic DoFn %v", u)
		}
		return graph.NewFn(&graph.DynFn{
			Name: u.Dynfn.Name,
			T:    t,
			Data: u.Dynfn.Data,
			Gen:  gen.(func(string, reflect.Type, []byte) reflectx.Func),
		})
	}
	if u.Fn != nil {
		fn, err := decodeUserFn(u.Fn)
		if err != nil {
			wrapped := errors.Wrap(err, "failed to decode userfn")
			return nil, errors.WithContextf(wrapped, "decoding DoFn %v", u)
		}
		fx, err := funcx.New(reflectx.MakeFunc(fn))
		if err != nil {
			wrapped := errors.Wrap(err, "failed to construct userfn")

View on GitHub (pinned to 12126d8942)