apache/beam · error
error encoding pane %v: non-speculative index value must be
Error message
error encoding pane %v: non-speculative index value must be equal to -1 if the pane timing is early
What it means
EncodePane validates pane metadata before encoding: when the pane timing is typex.PaneEarly, the NonSpeculativeIndex must be exactly -1 (the sentinel for 'no speculative index'). This error means a typex.PaneInfo value violates that invariant, so the coder refuses to serialize it rather than producing a corrupt stream.
Source
Thrown at sdks/go/pkg/beam/core/graph/coder/panes.go:47
pane := byte(0)
if v.IsFirst {
pane |= 0x01
}
if v.IsLast {
pane |= 0x02
}
pane |= byte(v.Timing << 2)
switch {
case (v.Index == 0 && v.NonSpeculativeIndex == 0) || v.Timing == typex.PaneUnknown:
// The entire pane info is encoded as a single byte
paneByte := []byte{pane}
w.Write(paneByte)
case v.Index == v.NonSpeculativeIndex || v.Timing == typex.PaneEarly:
// The pane info is encoded as this byte plus a single VarInt encoded integer
if v.Timing == typex.PaneEarly && v.NonSpeculativeIndex != -1 {
return fmt.Errorf("error encoding pane %v: non-speculative index value must be equal to -1 if the pane timing is early", v)
}
paneByte := []byte{pane | 1<<4}
w.Write(paneByte)
EncodeVarInt(v.Index, w)
default:
// The pane info is encoded as this byte plus two VarInt encoded integer
paneByte := []byte{pane | 2<<4}
w.Write(paneByte)
EncodeVarInt(v.Index, w)
EncodeVarInt(v.NonSpeculativeIndex, w)
}
return nil
}
// NewPane initializes the PaneInfo from a given byte.
// By default, PaneInfo is assigned to NoFiringPane.
func NewPane(b byte) typex.PaneInfo {
pn := typex.NoFiringPane()View on GitHub (pinned to 12126d8942)
Solutions
- Set NonSpeculativeIndex to -1 when creating PaneInfo values with Timing == PaneEarly.
- Use typex.PaneInfo constructors/helpers instead of struct literals so invariants hold.
- Audit custom runner/transform code that builds panes and reset the index for early panes.
- If this arises from the Beam runtime itself, file an issue with the Beam Go SDK with the pane value.
Example fix
// before
p := typex.PaneInfo{Timing: typex.PaneEarly, Index: 0, NonSpeculativeIndex: 0}
// after
p := typex.PaneInfo{Timing: typex.PaneEarly, Index: 0, NonSpeculativeIndex: -1} Defensive patterns
Strategy: validation
Validate before calling
func validPane(p typex.PaneInfo) bool {
return p.Timing != typex.PaneEarly || p.NonSpeculativeIndex == -1
} Type guard
func isEarlyPaneValid(p typex.PaneInfo) bool { return p.Timing != typex.PaneEarly || p.NonSpeculativeIndex == -1 } Try / catch
if err := panes.EncodePane(p, w); err != nil {
if strings.Contains(err.Error(), "non-speculative index") { log.Printf("invalid pane %v", p) }
return err
} Prevention
- Always build PaneInfo via typex helpers rather than raw struct literals.
- Enforce NonSpeculativeIndex == -1 for early-timing panes in custom runner code.
- Add unit tests round-tripping EncodePane/DecodePane for every pane timing.
When it happens
Trigger: Constructing a typex.PaneInfo with Timing set to PaneEarly but NonSpeculativeIndex set to something other than -1, then calling panes.EncodePane (directly or via Encode/EncodeWindowedValueHeader/timer encoding paths).
Common situations: Custom pane bookkeeping in a runner or transform that tracks speculative indexes while also marking early panes; hand-built PaneInfo in tests; a runner bug emitting panes with default 0 index on early firings.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- varint too long
- error encoding byte: %v
- number of fields is less than byte array %v < %v
- WriteSimpleRowHeader a 0 length nils bit field: %v
- ReadSimpleRowHeader field count: %v, %v
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/dfa1ca394da60bae.
Report an issue: GitHub.