apache/beam · error

invalid registration type: %v

Error message

invalid registration type: %v

What it means

RegisterType derives a registry key via TypeKey(t), which only supports types with representable external keys (notably functions and certain unnamed/composite types are rejected). If no key can be derived, registering the type would be meaningless, so the library panics with the offending type.

Source

Thrown at sdks/go/pkg/beam/core/runtime/types.go:39

	"github.com/apache/beam/sdks/v2/go/pkg/beam/core/util/reflectx"
)

var types = make(map[string]reflect.Type)

// RegisterType inserts "external" types into a global type registry to bypass
// serialization and preserve full method information. It should be called in
// init() only. Returns the external key for the type.
func RegisterType(t reflect.Type) string {
	if initialized {
		panic("Init hooks have already run. Register type during init() instead.")
	}

	t = reflectx.SkipPtr(t)

	k, ok := TypeKey(t)
	if !ok {
		panic(fmt.Sprintf("invalid registration type: %v", t))
	}

	if v, exists := types[k]; exists && v != t {
		panic(fmt.Sprintf("type already registered for %v, and new type %v != %v (existing type)", k, t, v))
	}
	types[k] = t
	return k
}

// LookupType looks up a type in the global type registry by external key.
func LookupType(key string) (reflect.Type, bool) {
	t, ok := types[key]
	return t, ok
}

// TypeKey returns the external key of a given type. Returns false if not a
// candidate for registration.
func TypeKey(t reflect.Type) (string, bool) {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Register a named, concrete struct type (or pointer to it) instead of an anonymous/func/chan type.
  2. Use reflect.TypeOf on a concrete instance value, not on an interface variable, so the dynamic type is registered.
  3. If the type genuinely has no key (e.g. plain func), skip registry registration or wrap it in a named struct.

Example fix

// before
runtime.RegisterType(reflect.TypeOf(func(int) {})) // panics
// after
type MyFn struct{}
func (MyFn) ProcessElement(int) {}
runtime.RegisterType(reflect.TypeOf(MyFn{}))
Defensive patterns

Strategy: type-guard

Validate before calling

t := reflect.TypeOf(val)
if t.Kind() == reflect.Func || t.Kind() == reflect.Chan || t.Name() == "" {
    return fmt.Errorf("cannot register unsupported type %v", t)
}

Type guard

func registrable(t reflect.Type) bool {
    t = reflectx.SkipPtr(t)
    _, ok := runtime.TypeKey(t) // same check the library performs
    return ok
}

Prevention

When it happens

Trigger: Passing a reflect.Type that TypeKey cannot handle — typically a func type without a proper named signature, an unexported/anonymous type, or a similarly unsupported kind (e.g. chan, interface) — to runtime.RegisterType (directly or via RegisterDoFn/RegisterCoder).

Common situations: Registering anonymous struct or func literals with reflect.TypeOf; registering a variable of interface or channel type by mistake; calling RegisterType on a DoFn wrapper type that isn't a struct.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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