apache/beam · error

marshalling time

Error message

marshalling time: %v

What it means

Beam's default coder for time.Time serializes values using MarshalText for higher precision. If MarshalText fails during encoding of a pipeline element, the error is wrapped as "marshalling time". This is rare since time.Time.MarshalText almost never fails.

Solutions

  1. Inspect the wrapped error to find the offending element and how the time.Time was constructed.
  2. Construct time.Time values only via time.Now(), time.Parse, etc.; avoid unsafe zero-value or reflection-built times.
  3. If serialization is not needed, convert times to strings/ints before inserting into PCollections.
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := t.MarshalText(); err != nil {
    return fmt.Errorf("element time is unencodable: %w", err)
}

Type guard

func isEncodableTime(t time.Time) bool { _, err := t.MarshalText(); return err == nil }

Try / catch

if err := beamRun(ctx, p); err != nil {
    if strings.Contains(err.Error(), "marshalling time") {
        // inspect elements for badly constructed time.Time values
    }
}

Prevention

When it happens

Trigger: Encoding a time.Time element in a Beam pipeline when t.MarshalText() returns an error (e.g. a time value with an unrepresentable state, generally from unsafe construction of a Time struct).

Common situations: Pipelines transmitting time.Time elements across worker boundaries; corrupt or zero-valued times created via unsafe.Inspect/time.Time{} manipulation rather than time.Now/time.Parse.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/encoding.go:276

				return EncodedCoder{}, err
			}
			return EncodedCoder{Coder: Coder{coder: c}}, nil
		},
		nil
}

func timeEnc(reflect.Type) (func(any, io.Writer) error, error) {
	return func(iface any, w io.Writer) error {
		if err := coder.WriteSimpleRowHeader(1, w); err != nil {
			return errors.Wrap(err, "encoding time.Time schema override")
		}
		t := iface.(time.Time)
		// We use the text marshalling rather than the binary marshalling
		// since it has more precision. Apparently some info isn't included
		// in the binary marshal.
		data, err := t.MarshalText()
		if err != nil {
			return fmt.Errorf("marshalling time: %v", err)
		}
		if err := coder.EncodeBytes(data, w); err != nil {
			return err
		}
		return nil
	}, nil
}

func timeDec(reflect.Type) (func(io.Reader) (any, error), error) {
	return func(r io.Reader) (any, error) {
		if err := coder.ReadSimpleRowHeader(1, r); err != nil {
			return nil, errors.Wrap(err, "decoding time.Time schema override")
		}
		data, err := coder.DecodeBytes(r)
		if err != nil {
			return nil, errors.Wrap(err, "retrieving time data: %v")
		}
		t := time.Time{}

View on GitHub (pinned to 12126d8942)