apache/beam · error

StepConfig.InitialSplits must be >= 1. Got

Error message

StepConfig.InitialSplits must be >= 1. Got: %v

What it means

StepConfigBuilder.Build() in the Beam Go synthetic step panics when InitialSplits is less than 1. InitialSplits controls how many initial splits the synthetic step generates, and a zero or negative count is invalid. This fails fast during pipeline construction.

Solutions

  1. Set InitialSplits to at least 1 before calling Build().
  2. If the value is computed, guard against len(list) == 0 and fall back to 1.
  3. When deserializing config, apply a default (e.g. 1) when the field is missing or zero.

Example fix

// before
b := &synthetic.StepConfigBuilder{}
cfg := b.Build() // InitialSplits is 0
// after
b := (&synthetic.StepConfigBuilder{}).InitialSplits(1)
cfg := b.Build()
Defensive patterns

Strategy: validation

Validate before calling

if cfg.InitialSplits < 1 {
    return fmt.Errorf("InitialSplits must be >= 1, got %d", cfg.InitialSplits)
}

Prevention

When it happens

Trigger: Calling StepConfigBuilder.Build() after StepConfigBuilder.InitialSplits(0) or a negative value, or building from config where InitialSplits defaulted to 0 because it was never set.

Common situations: Forgetting to set InitialSplits on a zero-valued builder struct; loading config from JSON/env where the field was omitted; computing the split count from an empty slice length.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at sdks/go/pkg/beam/io/synthetic/step.go:244

// Each resulting restriction will have at least 1 element in it, and each
// element being emitted will be contained in exactly one restriction. That
// means that if the desired number of splits is greater than the OutputPerInput
// N, then N initial restrictions will be created, each containing 1 element.
//
// Valid values are in the range of [1, ...] and the default value is 1. Values
// of 0 (and below) are invalid as they would result in dropping elements that
// are expected to be emitted.
func (b *StepConfigBuilder) InitialSplits(val int) *StepConfigBuilder {
	b.cfg.InitialSplits = val
	return b
}

// Build constructs the StepConfig initialized by this builder. It also performs
// error checking on the fields, and panics if any have been set to invalid
// values.
func (b *StepConfigBuilder) Build() StepConfig {
	if b.cfg.InitialSplits <= 0 {
		panic(fmt.Sprintf("StepConfig.InitialSplits must be >= 1. Got: %v", b.cfg.InitialSplits))
	}
	if b.cfg.OutputPerInput < 0 {
		panic(fmt.Sprintf("StepConfig.OutputPerInput cannot be negative. Got: %v", b.cfg.OutputPerInput))
	}
	return b.cfg
}

// StepConfig is a struct containing all the configuration options for a
// synthetic step. It should be created via a StepConfigBuilder, not by directly
// initializing it (the fields are public to allow encoding).
type StepConfig struct {
	OutputPerInput int
	FilterRatio    float64
	Splittable     bool
	InitialSplits  int
}

View on GitHub (pinned to 12126d8942)