apache/beam · error
bind conflict for %v: %v != %v
Error message
bind conflict for %v: %v != %v
What it means
During generic binding in Satisfy (helper 'bind'), each universal (generic) type parameter is mapped by name to a concrete reflect.Type. This error is returned when the same generic type name would need to bind to two different concrete types, which would make the substitution inconsistent.
Source
Thrown at sdks/go/pkg/beam/core/funcx/signature.go:174
}
if err := matchOpt(in[:off], sig.OptArgs, m); err != nil {
return err
}
if err := matchReq(out[:len(sig.Return)], sig.Return); err != nil {
return err
}
return matchOpt(out[len(sig.Return):], sig.OptReturn, m)
}
func bind(list, models []reflect.Type, m map[string]reflect.Type) error {
for i, t := range models {
if !typex.IsUniversal(list[i]) {
continue
}
name := list[i].Name()
if current, ok := m[name]; ok && current != t {
return errors.Errorf("bind conflict for %v: %v != %v", name, current, t)
}
m[name] = t
}
return nil
}
func matchReq(list, models []reflect.Type) error {
for i, t := range list {
if typex.IsUniversal(t) {
continue // ok: if this was bad, there would be a bind conflict
}
model := models[i]
if t.Kind() == reflect.Interface && model.Implements(t) {
continue
}
if model != t {
return &TypeMismatchError{Got: t, Want: model}View on GitHub (pinned to 12126d8942)
Solutions
- Make the types consistent so every occurrence of a generic name binds to the same concrete type.
- If the types are genuinely different, use distinct generic type names in the Signature.
- Check the inputs/outputs being fed to the function; ensure upstream producers emit the declared type.
Example fix
// before func process(kv KV<X, X>) ... // KV<int,string> input: X binds to both int and string -> conflict // after func process(kv KV<X, Y>) ... // use two distinct generics
Defensive patterns
Strategy: validation
Validate before calling
in, out := fnTypeParams(fn)
bindings := map[string]reflect.Type{}
for _, t := range append(in, out...) {
if name := genericName(t); name != "" {
if prev, ok := bindings[name]; ok && prev != t {
return fmt.Errorf("generic %s bound to both %v and %v", name, prev, t)
}
bindings[name] = t
}
} Prevention
- Ensure every generic type name binds to exactly one concrete type across parameters and returns.
- Use distinct variable names (X, Y) for differing input/output types.
- Check upstream PCollection element types match the declared generic.
When it happens
Trigger: Calling Satisfy with a function where one named generic (e.g. X) appears in multiple parameter or return positions that have different concrete types, e.g. fn func(A, B) (int, error) where A and B both refer to generic X.
Common situations: DoFn methods that process input of one type but emit a mismatched output type while the signature declares them as the same generic; typos in type parameters causing two generics to share a name; passing mixed-type collections (e.g. KV<A,B>) where a single type was expected.
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
- optional generic parameter not bound %v
- cannot substitute type %v with %v, already defined as %v
- %v cannot bind to %v
- typex.Bind: %v is not assignable to %v
- Type interface{} isn't a supported PCollection type
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/727e58eeb578379d.
Report an issue: GitHub.