apache/beam · error

typex.Bind: %v is not assignable to %v

Error message

typex.Bind: %v is not assignable to %v

What it means

typex.Bind creates a binding from type variables (models) to concrete Go types. Each actual type must be structurally assignable to its corresponding model; if IsStructurallyAssignable fails, Bind refuses to build the map and returns this error naming the model and the offending type.

Source

Thrown at sdks/go/pkg/beam/core/typex/fulltype.go:360

	return true
}

// Bind returns a substitution from universals to types in the given models,
// such as {"T" -> X, "X" -> int}. Each model must be assignable to the
// corresponding type. For example, Bind(KV<T,int>, KV<string, int>) would
// produce {"T" -> string}.
func Bind(types, models []FullType) (map[string]reflect.Type, error) {
	if len(types) != len(models) {
		return nil, errors.Errorf("typex.Bind: invalid number of models: %v, want %v", len(models), len(types))
	}

	m := make(map[string]reflect.Type)
	for i := 0; i < len(types); i++ {
		t := types[i]
		model := models[i]

		if !IsStructurallyAssignable(model, t) {
			return nil, errors.Errorf("typex.Bind: %v is not assignable to %v", model, t)
		}
		if err := walk(t, model, m); err != nil {
			return nil, err
		}
	}
	return m, nil
}

func walk(t, model FullType, m map[string]reflect.Type) error {
	switch t.Class() {
	case Universal:
		// By checking that the model is assignable to t, we know that they are
		// structurally compatible. We rely on the exact reflect.Type in the
		// Aggregate case to pick the correct binding, i.e., we do not need to
		// construct such a type.

		name := t.Type().Name()
		if current, ok := m[name]; ok && current != model.Type() {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Check the two %v values in the message: the first is the model (type variable) and the second your concrete type; align the concrete type's structure with the model.
  2. Verify argument order — Bind expects (models, types); swapping them produces spurious assignment failures.
  3. Use typex.New / typex.T, typex.X etc. to construct models matching the exact container/composite shape of your runtime type.
  4. Print reflect.TypeOf on the value and compare element kinds (slice vs array, key/value types) with the model before calling Bind.

Example fix

// before
typex.Bind([]typex.FullType{typex.New(typex.X(typex.T))}, []typex.FullType{typex.New(reflect.TypeOf(42))}) // X<int> model vs int

// after
typex.Bind([]typex.FullType{typex.New(typex.T)}, []typex.FullType{typex.New(reflect.TypeOf(42))})
Defensive patterns

Strategy: validation

Validate before calling

func canBind(models, types []typex.FullType) bool {
    if len(models) != len(types) {
        return false
    }
    for i := range models {
        if !typex.IsStructurallyAssignable(models[i], types[i]) {
            return false
        }
    }
    return true
}

Type guard

if mt, ok := value.(typex.FullType); ok && typex.IsStructurallyAssignable(model, mt) { /* safe to Bind */ }

Try / catch

m, err := typex.Bind(models, types)
if err != nil {
    return fmt.Errorf("type binding failed: %w", err)
}

Prevention

When it happens

Trigger: Calling typex.Bind(models, types) where the i-th concrete type does not structurally match the i-th model — e.g. binding an int against a variable typed as X<int>, mismatched container element types, or supplying fewer/mismatched pairs so models[i] cannot accept types[i].

Common situations: Users defining a DoFn or CombineFn with generic type variables pass user data whose shape doesn't match the declared variable structure; common after refactoring a pipeline's PCollection element type (e.g. T to string) without updating the typex.NewVariable/T types passed to Bind.

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/22778e38e5354752. Report an issue: GitHub.