apache/beam · error

position claimed is out of bounds of the restriction

Error message

position claimed is out of bounds of the restriction

What it means

offsetrange.Tracker.TryClaim rejects a claimed position below the restriction's Start. Claiming outside the restriction [Start, End) violates the Beam restriction-tracker contract, so the tracker records this error, marks itself stopped, and returns false. The framework reports the stored error at element completion.

Source

Thrown at sdks/go/pkg/beam/io/rtrackers/offsetrange/offsetrange.go:168

// successfully claims it if the position is greater than the previously claimed position and within
// the restriction. Claiming a position at or beyond the end of the restriction signals that the
// entire restriction has been processed and is now done, at which point this method signals to end
// processing.
//
// The tracker stops with an error if a claim is attempted after the tracker has signalled to stop,
// if a position is claimed before the start of the restriction, or if a position is claimed before
// the latest successfully claimed.
func (tracker *Tracker) TryClaim(rawPos any) bool {
	if tracker.stopped {
		tracker.err = errors.New("cannot claim work after restriction tracker returns false")
		return false
	}

	pos := rawPos.(int64)
	tracker.attempted = pos
	if pos < tracker.rest.Start {
		tracker.stopped = true
		tracker.err = errors.New("position claimed is out of bounds of the restriction")
		return false
	}
	if pos <= tracker.claimed {
		tracker.stopped = true
		tracker.err = errors.New("cannot claim a position lower than the previously claimed position")
		return false
	}

	tracker.claimed = pos
	if pos >= tracker.rest.End {
		tracker.stopped = true
		return false
	}
	return true
}

// GetError returns the error that caused the tracker to stop, if there is one.
func (tracker *Tracker) GetError() error {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Start claiming from tracker's restriction Start: use tracker.TryClaim(rest.GetStart()) as the first position, not 0.
  2. Access the restriction via the RestrictionTracker's GetRestriction/GetError-aware API rather than caching the original input range.
  3. Verify split/residual logic hands the DoFn the correct sub-restriction that includes the positions being claimed.

Example fix

// before
for i := 0; i < len(items); i++ { tracker.TryClaim(int64(i)) } // 0 may be < rest.Start
// after
rest := tracker.GetRestriction().(offsetrange.Restriction)
for i := rest.GetStart(); i < rest.GetEnd(); i++ {
    if !tracker.TryClaim(i) { break }
}
Defensive patterns

Strategy: validation

Validate before calling

rest := tracker.GetRestriction().(offsetrange.Restriction)
if pos < rest.GetStart() {
    return fmt.Errorf("pos %d below restriction start %d", pos, rest.GetStart())
}

Type guard

func inRestriction(rest offsetrange.Restriction, pos int64) bool {
    return pos >= rest.GetStart() && pos < rest.GetEnd()
}

Try / catch

if !tracker.TryClaim(pos) {
    return tracker.GetError() // includes out-of-bounds claim errors
}

Prevention

When it happens

Trigger: Calling TryClaim(pos) where pos < rest.Start — e.g. a ProcessElement that starts iterating from the original range's beginning instead of the current restriction's Start after a split/rescale assigned a sub-range.

Common situations: DoFns that hardcode an offset of 0 rather than reading rest.GetStart(); split-driven code resuming from stale positions; using the wrong restriction tracker instance with a narrower restriction.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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