{"record":{"id":"edcff6aca07e8a39","repo":"apache/beam","slug":"unable-to-convert-key-of-v-to-schema-field","errorCode":null,"errorMessage":"unable to convert key of %v to schema field","messagePattern":"unable to convert key of (.+?) to schema field","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/runtime/graphx/schema/schema.go","lineNumber":590,"sourceCode":"\t}\n\tif ftype != nil {\n\t\treturn &pipepb.FieldType{\n\t\t\tTypeInfo: &pipepb.FieldType_LogicalType{\n\t\t\t\tLogicalType: &pipepb.LogicalType{\n\t\t\t\t\tUrn:            lID,\n\t\t\t\t\tRepresentation: ftype,\n\t\t\t\t\t// TODO(BEAM-9615): Handle type Arguments.\n\t\t\t\t},\n\t\t\t},\n\t\t}, nil\n\t}\n\n\tt := ot\n\tswitch t.Kind() {\n\tcase reflect.Ptr:\n\t\tvt, err := r.reflectTypeToFieldType(t.Elem())\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"unable to convert key of %v to schema field\", ot)\n\t\t}\n\t\tvt.Nullable = true\n\t\treturn vt, nil\n\tcase reflect.Map:\n\t\tkt, err := r.reflectTypeToFieldType(t.Key())\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"unable to convert key of %v to schema field\", ot)\n\t\t}\n\t\tvt, err := r.reflectTypeToFieldType(t.Elem())\n\t\tif err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"unable to convert value of %v to schema field\", ot)\n\t\t}\n\t\treturn &pipepb.FieldType{\n\t\t\tTypeInfo: &pipepb.FieldType_MapType{\n\t\t\t\tMapType: &pipepb.MapType{\n\t\t\t\t\tKeyType:   kt,\n\t\t\t\t\tValueType: vt,\n\t\t\t\t},","sourceCodeStart":572,"sourceCodeEnd":608,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/runtime/graphx/schema/schema.go#L572-L608","documentation":"Raised in reflectTypeToFieldType when the input is a pointer and converting its element type (t.Elem()) fails. Despite saying 'key of %v', the pointer branch is converting the pointee — the wrap means 'unable to convert the pointed-to type'. On success the pointer field is marked nullable.","triggerScenarios":"Converting a schema field of pointer type (*T) where T (or something nested inside T) fails reflectTypeToFieldType — e.g. *map[BadKey]string, **T chains, or pointers to unregistered custom structs.","commonSituations":"Optional fields implemented as pointers in PCollection element structs; nilable custom types used as map values or struct fields; deep pointer nesting.","solutions":["Inspect the wrapped error for the failing element type.","Make the pointee schema-convertible (register a logical type or change its kind).","Replace the pointer with a value plus presence field, or drop the field.","Flatten excessive pointer nesting (**T), which adds conversion failure points."],"exampleFix":"// before\ntype Row struct { Opt *map[CustomKey]string }\n// after\ntype Row struct { Opt map[string]string }","handlingStrategy":"validation","validationCode":"if t.Kind() == reflect.Ptr {\n    if err := schemaSafe(t.Elem()); err != nil {\n        return fmt.Errorf(\"pointee %v not schema-safe: %w\", t.Elem(), err)\n    }\n}","typeGuard":"func isNullableSchemaSafe(t reflect.Type) bool {\n    return t.Kind() == reflect.Ptr && schemaSafe(t.Elem()) == nil\n}","tryCatchPattern":"schm, err := reg.FromType(t)\nif err != nil && strings.Contains(err.Error(), \"unable to convert key of\") && t.Kind() == reflect.Ptr {\n    return nil, fmt.Errorf(\"pointee of %v failed conversion: %w\", t, err)\n}","preventionTips":["Avoid **T and pointers to exotic containers as fields.","Ensure pointee types are registered/convertible.","Prefer value fields plus presence flags for optionality.","Test pointer-bearing structs with FromType in CI."],"tags":["go","schema","pointer","reflection"],"backgroundTag":"schema-validation-failed","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}