apache/beam · error

cannot make schema encoder for type %v as it has unexported

Error message

cannot make schema encoder for type %v as it has unexported fields such as %s.

What it means

When RowEncoderBuilder.RequireAllFieldsExported is set, encoding a struct containing unexported fields fails: Beam cannot read or write those fields reflectively, so strict mode errors out instead of silently skipping them.

Source

Thrown at sdks/go/pkg/beam/core/graph/coder/row_encoder.go:318

				// 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
			}})
			continue
		}
		enc, err := b.encoderForSingleTypeReflect(sf.Type)
		if err != nil {
			return nil, err
		}
		coder.fields = append(coder.fields, enc)
	}

	return func(rv reflect.Value, w io.Writer) error {
		if err := writeRowHeader(rv, w); err != nil {
			return err

View on GitHub (pinned to 12126d8942)

Solutions

  1. Export all fields of the struct, or remove unexported fields from the encoded type
  2. Disable RequireAllFieldsExported so unexported fields are skipped with a no-op coder
  3. Implement a custom coder for the type

Example fix

// before
type Rec struct { Name string; secret string }
// after
type Rec struct { Name string; Secret string }
Defensive patterns

Strategy: validation

Validate before calling

func hasUnexportedFields(t reflect.Type) bool {
    if t.Kind() != reflect.Struct { return false }
    for i := 0; i < t.NumField(); i++ {
        if !t.Field(i).IsExported() { return true }
    }
    return false
}

Type guard

func isFullyExported(v any) bool { return !hasUnexportedFields(reflect.TypeOf(v)) }

Try / catch

if _, err := (coder.RowEncoderBuilder{RequireAllFieldsExported: true}).Build(t); err != nil {
    return fmt.Errorf("strict schema encoding requires exported fields: %w", err)
}

Prevention

When it happens

Trigger: Calling encoderForStructReflect on a struct with unexported fields while the builder was created with RequireAllFieldsExported = true (e.g. from a strict schema path).

Common situations: Users relying on schema coding with idiomatic Go structs that keep private fields; strict coders used in DoFn serialization checks.

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/ed8c3d9b7a66a7e6. Report an issue: GitHub.