apache/beam · error
cannot make schema encoder for type %v as it has an embedded
Error message
cannot make schema encoder for type %v as it has an embedded field of a pointer to an unexported type %v. See https://golang.org/issue/21357
What it means
Beam cannot build a schema encoder for a struct with an embedded pointer to an unexported type, because reflect cannot safely construct that embedded value (golang.org/issue/21357). The encoder refuses rather than produce broken encodings.
Source
Thrown at sdks/go/pkg/beam/core/graph/coder/row_encoder.go:306
var coder typeEncoderReflect
for i := 0; i < t.NumField(); i++ {
coder.debug = append(coder.debug, t.Field(i).Name+" "+t.Field(i).Type.String())
sf := t.Field(i)
isUnexported := sf.PkgPath != ""
if sf.Anonymous {
ft := sf.Type
if ft.Kind() == reflect.Ptr {
// If a struct embeds a pointer to an unexported type,
// it is not possible to set a newly allocated value
// since the field is unexported.
//
// See https://golang.org/issue/21357
//
// Since the values are created by this package reflectively,
// there's no work around like pre-allocating the field
// manually.
if isUnexported {
return nil, errors.Errorf("cannot make schema encoder for type %v as it has an embedded field of a pointer to an unexported type %v. See https://golang.org/issue/21357", t, ft.Elem())
}
ft = ft.Elem()
}
if isUnexported && ft.Kind() != reflect.Struct {
// Ignore embedded fields of unexported non-struct types.
continue
}
// Do not ignore embedded fields of unexported struct types
// since they may have exported fields.
} else if isUnexported {
if b.RequireAllFieldsExported {
return nil, errors.Errorf("cannot make schema encoder for type %v as it has unexported fields such as %s.", t, sf.Name)
}
// Silently ignore, since we can't do anything about it.
// Add a no-op coder to fill in field index
coder.fields = append(coder.fields, typeEncoderFieldReflect{encode: func(rv reflect.Value, w io.Writer) error {
return nil
}})View on GitHub (pinned to 12126d8942)
Solutions
- Remove the embedded pointer to the unexported type; embed an exported type instead
- Flatten the embedded fields into the struct explicitly
- Use a custom coder instead of reflective schema coding for this type
Example fix
// before
type Wrapper struct { *base }
// after
type Wrapper struct { Base } // where Base is exported Defensive patterns
Strategy: validation
Validate before calling
func hasEmbeddedUnexportedPtr(t reflect.Type) bool {
if t.Kind() != reflect.Struct { return false }
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.Anonymous && f.Type.Kind() == reflect.Ptr && !f.Type.Elem().IsExported() {
return true
}
}
return false
} Type guard
func isSchemaEncodableStruct(t reflect.Type) bool { return !hasEmbeddedUnexportedPtr(t) } Try / catch
if _, err := (coder.RowEncoderBuilder{}).Build(t); err != nil {
return fmt.Errorf("struct %s not schema-encodable: %w", t, err)
} Prevention
- Never embed pointers to unexported types in pipeline element structs
- Prefer exported embedded structs
- Run schema-coder build checks as part of unit tests
When it happens
Trigger: Encoding a struct that embeds *unexportedType, e.g. type T struct { *foo }; passing T (or a struct containing it) to reflective schema row encoding.
Common situations: Internal-ish embedded pointer types (common with generated or package-private base types) surfacing in PCollection elements.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- cannot make schema encoder for type %v as it has unexported
- inferCoder failed: interface type %v has no coder registered
- errIllegalParametersInIter
- Type %v of kind %v not allowed, must be ptr type
- not a function: %v
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/27759a012b1f8163.
Report an issue: GitHub.