{"record":{"id":"dfa38a7d00e0950c","repo":"apache/beam","slug":"non-struct-type-received-in-structtoschema-v-is-kind-v","errorCode":null,"errorMessage":"non struct type received in structToSchema: %v is kind %v","messagePattern":"non struct type received in structToSchema: (.+?) is kind (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/core/runtime/graphx/schema/schema.go","lineNumber":503,"sourceCode":"\t\t\t},\n\t\t},\n\t}\n}\n\n// fromLogicalOption returns the logical type id of this top\n// level type if this schema has a logical equivalent.\nfunc fromLogicalOption(opts []*pipepb.Option) (string, bool) {\n\to := checkOptions(opts, optGoLogicalUrn)\n\tif o == nil {\n\t\treturn \"\", false\n\t}\n\tlID := o.GetValue().GetAtomicValue().GetString_()\n\treturn lID, true\n}\n\nfunc (r *Registry) structToSchema(t reflect.Type) (*pipepb.Schema, error) {\n\tif t.Kind() != reflect.Struct {\n\t\treturn nil, errors.Errorf(\"non struct type received in structToSchema: %v is kind %v\", t, t.Kind())\n\t}\n\tif schm, ok := r.typeToSchema[t]; ok {\n\t\treturn schm, nil\n\t}\n\n\tftype, lID, err := r.logicalTypeToFieldType(t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif ftype != nil {\n\t\tschm := ftype.GetRowType().GetSchema()\n\t\tschm = proto.Clone(schm).(*pipepb.Schema)\n\t\tschm.Options = append(schm.Options, logicalOption(lID))\n\t\tschm.Id = getUUID(t)\n\t\tr.typeToSchema[t] = schm\n\t\tr.idToType[schm.GetId()] = t\n\t\treturn schm, nil\n\t}","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/core/runtime/graphx/schema/schema.go#L485-L521","documentation":"Registry.structToSchema asserts its input is a struct kind; any other kind reaching it is an internal misuse. This is an invariant error — its callers (fromType, reflectTypeToFieldType) are supposed to pre-filter, so a non-struct here indicates a logic bug or unexpected registry state rather than unvalidated user input.","triggerScenarios":"An internal call path (fromType on a non-cached, non-logical type, or reflectTypeToFieldType on a field) passes a non-struct reflect.Type into structToSchema — e.g. pointer handling skipped incorrectly or a map/array kind leaking through the dispatch switch.","commonSituations":"Local forks/patches to the schema package; surprising kinds from type aliases after skipping pointers; registry state where a field type bypasses the normal kind switch in reflectTypeToFieldType.","solutions":["Verify with reflectx.SkipPtr(t).Kind() what kind actually arrives; debug the caller passing it.","Use the public FromType API (which validates kind) rather than internal helpers.","Check for local modifications to schema.go that bypass kind dispatch.","File a Beam bug with the offending type if hit through unmodified public APIs."],"exampleFix":"// before\nschm, err := reg.structToSchema(reflect.TypeOf(42)) // internal misuse\n// after\nif reflectx.SkipPtr(t).Kind() != reflect.Struct { return nil, fmt.Errorf(\"not a struct: %v\", t) }\nschm, err := reg.FromType(t) // public path validates","handlingStrategy":"type-guard","validationCode":"if reflectx.SkipPtr(t).Kind() != reflect.Struct {\n    return fmt.Errorf(\"structToSchema requires struct, got %v\", reflectx.SkipPtr(t).Kind())\n}","typeGuard":"func isStructKind(t reflect.Type) bool { return reflectx.SkipPtr(t).Kind() == reflect.Struct }","tryCatchPattern":"schm, err := reg.FromType(t)\nif err != nil && strings.Contains(err.Error(), \"non struct type received\") {\n    return nil, fmt.Errorf(\"internal bug: non-struct reached structToSchema: %v\", t)\n}","preventionTips":["Call the public FromType API instead of internal helpers.","Never patch schema.go dispatch without updating callers.","Add unit tests covering alias and pointer-normalized kinds.","Report upstream via a Beam bug if reached via public APIs."],"tags":["go","schema","internal-error","reflection"],"backgroundTag":"internal-invariant-violation","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"}