apache/beam · error
unable to convert map key type
Error message
unable to convert map key type
What it means
Wrapper error raised when the key type of a MapType field fails conversion in Registry.fieldTypeToReflectType. Beam/Go require map keys to be comparable and schema-representable; if the key's FieldType cannot be turned into a reflect.Type, this error names the map context. Note the adjacent comment: reflect.MapOf panics for invalid keys (slices/iterables), so key failures should be caught here first.
Solutions
- Inspect the wrapped error to find why the key type failed
- Change the map key to a schema-supported comparable atomic (string, int, bool, bytes)
- Register the key's logical type so it resolves to a comparable Go type
- Restructure the schema to use a repeated row of {key,value} instead of a map when keys aren't convertible
Example fix
// before: map with array key
// after: represent as list of pairs
fields: [ {name: "entries", type: array<row{key: string, value: int64}>} ] Defensive patterns
Strategy: validation
Validate before calling
func mapKeysSchemaSafe(s *pipepb.Schema) error {
for _, f := range s.GetFields() {
if mt := f.GetType().GetMapType(); mt != nil {
if mt.GetKeyType().GetAtomicType() == pipepb.AtomicType_ATOMIC_TYPE_UNSPECIFIED {
return fmt.Errorf("map field %q key must be an atomic type", f.GetName())
}
}
}
return nil
} Try / catch
if err != nil && strings.Contains(err.Error(), "unable to convert map key type") {
return fmt.Errorf("map key must be a comparable atomic: %w", err)
} Prevention
- Only use atomic (string/int/bool/bytes) map keys in schemas
- Model complex keys as arrays of key/value rows instead of maps
- Remember Go's reflect.MapOf panics on non-comparable keys — validate before conversion
When it happens
Trigger: toType/fieldToStructField encountering a schema MapType whose KeyType fails fieldTypeToReflectType — e.g. key is an array type, logical type resolving to a slice, or unknown atomic.
Common situations: Schemas produced by other SDKs (Java/Python allow richer map key logical types) or hand-built schemas with non-convertible keys being loaded via ToType in Go.
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
- beam.RegisterSchemaProvider: schema type provider for
- beam.RegisterSchemaProvider: unsupported type kind for…
- cannot convert schema field
- invalid logical type, bad id
- invalid schema type
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/20463d1d369d8de5.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/runtime/graphx/schema/schema.go:778
func (r *Registry) fieldTypeToReflectType(sft *pipepb.FieldType, opts []*pipepb.Option) (reflect.Type, error) {
var t reflect.Type
switch sft.GetTypeInfo().(type) {
case *pipepb.FieldType_AtomicType:
var ok bool
if t, ok = atomicTypeToReflectType[sft.GetAtomicType()]; !ok {
return nil, errors.Errorf("unknown atomic type: %v", sft.GetAtomicType())
}
case *pipepb.FieldType_ArrayType:
rt, err := r.fieldTypeToReflectType(sft.GetArrayType().GetElementType(), nil)
if err != nil {
return nil, errors.Wrap(err, "unable to convert array element type")
}
t = reflect.SliceOf(rt)
case *pipepb.FieldType_MapType:
kt, err := r.fieldTypeToReflectType(sft.GetMapType().GetKeyType(), nil)
if err != nil {
return nil, errors.Wrap(err, "unable to convert map key type")
}
vt, err := r.fieldTypeToReflectType(sft.GetMapType().GetValueType(), nil)
if err != nil {
return nil, errors.Wrap(err, "unable to convert map value type")
}
t = reflect.MapOf(kt, vt) // Panics for invalid map keys (slices/iterables)
case *pipepb.FieldType_RowType:
rt, err := r.toType(sft.GetRowType().GetSchema())
if err != nil {
return nil, errors.Wrapf(err, "unable to convert row type: %v", sft.GetRowType().GetSchema().GetId())
}
t = rt
// case *pipepb.FieldType_IterableType:
// TODO(BEAM-9615): handle IterableTypes (eg. CoGBK values)
case *pipepb.FieldType_LogicalType:
lst := sft.GetLogicalType()
identifier := lst.GetUrn()View on GitHub (pinned to 12126d8942)