{"record":{"id":"a4ce011427d8df4b","repo":"antlr/antlr4","slug":"seek-to-index-outside-buffer-index-not-in-bu-a4ce01","errorCode":null,"errorMessage":"seek to index outside buffer: ${index} not in ${bufferStartIndex}..${bufferStartIndex+n}","messagePattern":"seek to index outside buffer: (.+?) not in (.+?)\\.\\.(.+?)","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"runtime/CSharp/src/UnbufferedTokenStream.cs","lineNumber":347,"sourceCode":"            {\n                return;\n            }\n            if (index > currentTokenIndex)\n            {\n                Sync(index - currentTokenIndex);\n                index = Math.Min(index, GetBufferStartIndex() + n - 1);\n            }\n            int bufferStartIndex = GetBufferStartIndex();\n            int i = index - bufferStartIndex;\n            if (i < 0)\n            {\n                throw new ArgumentException(\"cannot seek to negative index \" + index);\n            }\n            else\n            {\n                if (i >= n)\n                {\n                    throw new NotSupportedException(\"seek to index outside buffer: \" + index + \" not in \" + bufferStartIndex + \"..\" + (bufferStartIndex + n));\n                }\n            }\n            p = i;\n            currentTokenIndex = index;\n            if (p == 0)\n            {\n                lastToken = lastTokenBufferStart;\n            }\n            else\n            {\n                lastToken = tokens[p - 1];\n            }\n        }\n\n        public virtual int Size\n        {\n            get\n            {","sourceCodeStart":329,"sourceCodeEnd":365,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/CSharp/src/UnbufferedTokenStream.cs#L329-L365","documentation":"After Seek() syncs forward (Sync(index - currentTokenIndex) then clamps index to bufferStartIndex + n - 1), the offset i = index - bufferStartIndex must satisfy i < n. NotSupportedException 'seek to index outside buffer' means the requested absolute index is at or past the last buffered token — typically because EOF was reached so Sync could not extend the buffer further.","triggerScenarios":"Seek(index) with index beyond bufferStartIndex + n - 1 when the lexer has hit EOF (Sync stops fetching); seeking past the end of input; computing an index from token.StopIndex+1 on the EOF token and seeking to it.","commonSituations":"Error recovery or custom parsing logic that seeks to 'nextTokenIndex + k' without checking whether input remains; tests with truncated input where the parser assumes more tokens exist; off-by-one when converting absolute token indices to buffer offsets.","solutions":["Clamp the target before seeking: index = Math.Min(index, stream.GetBufferStartIndex() + bufferedCount - 1)","Verify more input actually exists (the token at the index is not EOF) before seeking to it","Use CommonTokenStream and check index < stream.Size when full-input random access is required","Audit custom error-handling code that extrapolates indices past the last fetched token"],"exampleFix":"// before\nstream.Seek(targetIndex); // throws if targetIndex is past last buffered token at EOF\n\n// after\nint last = stream.GetBufferStartIndex() + n_buffered - 1;\nstream.Seek(Math.Min(targetIndex, last));","handlingStrategy":"validation","validationCode":"// C#: clamp the target to the last buffered token before seeking\nint lastBuffered = stream.GetBufferStartIndex() + bufferedCount - 1; // bufferedCount = n, or count via LT(k) until EOF\nint safeIndex = Math.Min(targetIndex, lastBuffered);\nstream.Seek(safeIndex);","typeGuard":null,"tryCatchPattern":"try { stream.Seek(targetIndex); } catch (NotSupportedException ex) when (ex.Message.Contains(\"outside buffer\")) { // input exhausted: EOF reached, no token exists at targetIndex; treat as unexpected end of input }","preventionTips":["Check that the token at the target index is not EOF before seeking to it","Compute indices from LT(1).TokenIndex rather than arithmetic that can overshoot","Use CommonTokenStream with a Size check when full random access is required"],"tags":["antlr","csharp","token-stream","seek","eof"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}