apache/beam · error
non struct type received in structToSchema
Error message
non struct type received in structToSchema: %v is kind %v
What it means
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.
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.
Example fix
// before
schm, err := reg.structToSchema(reflect.TypeOf(42)) // internal misuse
// after
if reflectx.SkipPtr(t).Kind() != reflect.Struct { return nil, fmt.Errorf("not a struct: %v", t) }
schm, err := reg.FromType(t) // public path validates Defensive patterns
Strategy: type-guard
Validate before calling
if reflectx.SkipPtr(t).Kind() != reflect.Struct {
return fmt.Errorf("structToSchema requires struct, got %v", reflectx.SkipPtr(t).Kind())
} Type guard
func isStructKind(t reflect.Type) bool { return reflectx.SkipPtr(t).Kind() == reflect.Struct } Try / catch
schm, err := reg.FromType(t)
if err != nil && strings.Contains(err.Error(), "non struct type received") {
return nil, fmt.Errorf("internal bug: non-struct reached structToSchema: %v", t)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- beam.RegisterSchemaProvider: unsupported type kind for…
- cannot convert field
- cannot convert to schema. FromType only converts structs to…
- cannot make schema for type
- Logical Types may not be registered with empty interface…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/dfa38a7d00e0950c.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/go/pkg/beam/core/runtime/graphx/schema/schema.go:503
},
},
}
}
// fromLogicalOption returns the logical type id of this top
// level type if this schema has a logical equivalent.
func fromLogicalOption(opts []*pipepb.Option) (string, bool) {
o := checkOptions(opts, optGoLogicalUrn)
if o == nil {
return "", false
}
lID := o.GetValue().GetAtomicValue().GetString_()
return lID, true
}
func (r *Registry) structToSchema(t reflect.Type) (*pipepb.Schema, error) {
if t.Kind() != reflect.Struct {
return nil, errors.Errorf("non struct type received in structToSchema: %v is kind %v", t, t.Kind())
}
if schm, ok := r.typeToSchema[t]; ok {
return schm, nil
}
ftype, lID, err := r.logicalTypeToFieldType(t)
if err != nil {
return nil, err
}
if ftype != nil {
schm := ftype.GetRowType().GetSchema()
schm = proto.Clone(schm).(*pipepb.Schema)
schm.Options = append(schm.Options, logicalOption(lID))
schm.Id = getUUID(t)
r.typeToSchema[t] = schm
r.idToType[schm.GetId()] = t
return schm, nil
}View on GitHub (pinned to 12126d8942)