{"record":{"id":"e506fa6d41fca219","repo":"apache/beam","slug":"position-claimed-is-out-of-bounds-of-the-restriction","errorCode":null,"errorMessage":"position claimed is out of bounds of the restriction","messagePattern":"position claimed is out of bounds of the restriction","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/io/rtrackers/offsetrange/offsetrange.go","lineNumber":168,"sourceCode":"// successfully claims it if the position is greater than the previously claimed position and within\n// the restriction. Claiming a position at or beyond the end of the restriction signals that the\n// entire restriction has been processed and is now done, at which point this method signals to end\n// processing.\n//\n// The tracker stops with an error if a claim is attempted after the tracker has signalled to stop,\n// if a position is claimed before the start of the restriction, or if a position is claimed before\n// the latest successfully claimed.\nfunc (tracker *Tracker) TryClaim(rawPos any) bool {\n\tif tracker.stopped {\n\t\ttracker.err = errors.New(\"cannot claim work after restriction tracker returns false\")\n\t\treturn false\n\t}\n\n\tpos := rawPos.(int64)\n\ttracker.attempted = pos\n\tif pos < tracker.rest.Start {\n\t\ttracker.stopped = true\n\t\ttracker.err = errors.New(\"position claimed is out of bounds of the restriction\")\n\t\treturn false\n\t}\n\tif pos <= tracker.claimed {\n\t\ttracker.stopped = true\n\t\ttracker.err = errors.New(\"cannot claim a position lower than the previously claimed position\")\n\t\treturn false\n\t}\n\n\ttracker.claimed = pos\n\tif pos >= tracker.rest.End {\n\t\ttracker.stopped = true\n\t\treturn false\n\t}\n\treturn true\n}\n\n// GetError returns the error that caused the tracker to stop, if there is one.\nfunc (tracker *Tracker) GetError() error {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/io/rtrackers/offsetrange/offsetrange.go#L150-L186","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Start claiming from tracker's restriction Start: use tracker.TryClaim(rest.GetStart()) as the first position, not 0.","Access the restriction via the RestrictionTracker's GetRestriction/GetError-aware API rather than caching the original input range.","Verify split/residual logic hands the DoFn the correct sub-restriction that includes the positions being claimed."],"exampleFix":"// before\nfor i := 0; i < len(items); i++ { tracker.TryClaim(int64(i)) } // 0 may be < rest.Start\n// after\nrest := tracker.GetRestriction().(offsetrange.Restriction)\nfor i := rest.GetStart(); i < rest.GetEnd(); i++ {\n    if !tracker.TryClaim(i) { break }\n}","handlingStrategy":"validation","validationCode":"rest := tracker.GetRestriction().(offsetrange.Restriction)\nif pos < rest.GetStart() {\n    return fmt.Errorf(\"pos %d below restriction start %d\", pos, rest.GetStart())\n}","typeGuard":"func inRestriction(rest offsetrange.Restriction, pos int64) bool {\n    return pos >= rest.GetStart() && pos < rest.GetEnd()\n}","tryCatchPattern":"if !tracker.TryClaim(pos) {\n    return tracker.GetError() // includes out-of-bounds claim errors\n}","preventionTips":["Always derive claim positions from the current restriction's Start/End, never from 0.","After splits, use the restriction passed to the DoFn, not the original input range.","Add tests that simulate split-then-process to catch stale-range bugs."],"tags":["go","apache-beam","restriction-tracker","out-of-bounds"],"backgroundTag":"value-out-of-range","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}