apache/beam · error

cannot make schema for type %v as it has an embedded field o

Error message

cannot make schema 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

When converting a Go struct into a schema, ignoreField rejects structs containing an embedded field that is a pointer to an unexported type. Because the schema decoder creates values reflectively, it cannot construct such fields (golang/go#21357), so registration fails early with this message.

Source

Thrown at sdks/go/pkg/beam/core/runtime/graphx/schema/schema.go:181

	}
	return false
}

func ignoreField(t reflect.Type, sf reflect.StructField) (ignore, isAnon bool, err error) {
	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 the decoder reflectively,
			// fail early here.
			if isUnexported {
				return false, false, errors.Errorf("cannot make schema 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.
			return true, true, nil
		}
		// Do not ignore embedded fields of unexported struct types
		// since they may have exported fields.
		return false, true, nil
	}
	if isUnexported {
		// Schemas can't handle unexported fields at all.
		return true, false, nil
	}
	if implements(sf.Type, sdfRtrackerType) {
		// ignoring sdf.Rtracker interface
		return true, false, nil

View on GitHub (pinned to 12126d8942)

Solutions

  1. Export the embedded type or embed a value/exported pointer instead of a pointer to an unexported type.
  2. Register an explicit custom coder for the outer type so schema conversion is bypassed.
  3. Flatten the needed fields of the unexported type into exported fields of the outer struct.

Example fix

// before
type Result struct { *config } // config is unexported
// after
type Result struct { Config *Config } // Config exported
Defensive patterns

Strategy: validation

Validate before calling

func hasUnexportedEmbeddedPtr(t reflect.Type) bool {
    for i := 0; i < t.NumField(); i++ {
        f := t.Field(i)
        if f.Anonymous && f.Type.Kind() == reflect.Ptr {
            return !f.Type.Elem().IsExported == nil // elem type unexported
        }
    }
    return false
}

Try / catch

if err != nil {
    if strings.Contains(err.Error(), "pointer to an unexported type") {
        // restructure the type or register a custom coder
    }
}

Prevention

When it happens

Trigger: registerType or structToSchema walks a struct type that embeds, e.g. `*privateType` where privateType is unexported, while generating the schema.

Common situations: Pipelines whose DoFns emit structs embedding pointers to unexported types (common with generated or package-private helper types); passing such types to beam.RowEncoder/schema conversion.

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


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/60e7b8f45c1e3038. Report an issue: GitHub.