apache/beam · error
initial splitting returned 0 restrictions.
Error message
initial splitting returned 0 restrictions.
What it means
The initial split function of an unexpanded Splittable DoFn must return at least one restriction. If n.splitInv.Invoke returns an empty slice, the executor cannot create any restriction trackers and fails fast with this error. The error is wrapped with the transform context naming the failing SDF.
Source
Thrown at sdks/go/pkg/beam/core/runtime/exec/sdf.go:1035
// because sizing information is unnecessary for unexpanded SDFs.
func (n *SdfFallback) ProcessElement(ctx context.Context, elm *FullValue, values ...ReStream) error {
if n.PDo.status != Active {
err := errors.Errorf("invalid status %v, want Active", n.PDo.status)
return errors.WithContextf(err, "%v", n)
}
rest, err := n.initRestInv.Invoke(ctx, elm)
if err != nil {
return err
}
splitRests, err := n.splitInv.Invoke(ctx, elm, rest)
if err != nil {
return err
}
if len(splitRests) == 0 {
err := errors.Errorf("initial splitting returned 0 restrictions.")
return errors.WithContextf(err, "%v", n)
}
for _, splitRest := range splitRests {
rt, err := n.trackerInv.Invoke(ctx, splitRest)
if err != nil {
return err
}
mainIn := &MainInput{
Key: *elm,
Values: values,
RTracker: rt,
}
if err := n.PDo.processMainInput(mainIn); err != nil {
return err
}
}View on GitHub (pinned to 12126d8942)
Solutions
- Make SplitRestriction always return at least one restriction, even a trivial/empty one, for any input.
- Check any filtering or count computation in SplitRestriction that can yield zero splits for valid inputs.
- Return an error instead of an empty slice when splitting genuinely cannot proceed, to give a clearer failure.
- Use the transform name in the error context to find the offending SDF and add a unit test for its SplitRestriction.
Example fix
// before
func (fn *mySdf) SplitRestriction(el string, rest watermarksInterval) []watermarksInterval {
if len(el) < 10 { return nil } // 0 restrictions -> runtime error
...
}
// after
func (fn *mySdf) SplitRestriction(el string, rest watermarksInterval) []watermarksInterval {
if len(el) < 10 { return []watermarksInterval{rest} } // always return at least one
...
} Defensive patterns
Strategy: validation
Validate before calling
splits := fn.SplitRestriction(el, rest)
if len(splits) == 0 {
return fmt.Errorf("SplitRestriction returned 0 restrictions for %v", el)
} Try / catch
if err != nil {
if strings.Contains(err.Error(), "initial splitting returned 0 restrictions") {
// fix SplitRestriction for the transform named in the context
}
return err
} Prevention
- Always return at least one restriction from SplitRestriction.
- Add a unit test asserting non-empty output for representative inputs.
- Avoid filter logic that can eliminate all splits.
When it happens
Trigger: A user SDF's SplitRestriction returns an empty slice (e.g. filtering out all candidate restrictions because inputs are empty, out of range, or a default case returns nil). Raised in SdfFallback.ProcessElement at sdf.go:1035 right after initial splitting.
Common situations: Custom SplitRestriction implementations that return nil/empty when the element has no data, or that cap split count to a computed value which is 0 for the given input. Also occurs when the restriction doesn't overlap the element's valid range.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- SplitRestriction has unexpected number of parameters: %v
- CreateWatermarkEstimator fn %v has unexpected number of para
- InitialWatermarkEstimatorState fn %v has unexpected number o
- WatermarkEstimatorState fn %v has unexpected number of param
- CreateInitialRestriction has unexpected number of parameters
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/d7f98ba02b47f875.
Report an issue: GitHub.