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
- Inspect the wrapped error to find the offending element and how the time.Time was constructed.
- Construct time.Time values only via time.Now(), time.Parse, etc.; avoid unsafe zero-value or reflection-built times.
- 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
- Only construct time.Time via time.Now/time.Parse/time.Unix.
- Avoid zero-value or reflection-built time.Time in pipeline elements.
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)