{"record":{"id":"994dd3e139c3c805","repo":"antlr/antlr4","slug":"get-i-outside-buffer-bufferstartindex-b","errorCode":null,"errorMessage":"get(${i}) outside buffer: ${bufferStartIndex}..${bufferStartIndex+n}","messagePattern":"get\\((.+?)\\) outside buffer: (.+?)\\.\\.(.+?)","errorType":"exception","errorClass":"ArgumentOutOfRangeException","httpStatus":null,"severity":"error","filePath":"runtime/CSharp/src/UnbufferedTokenStream.cs","lineNumber":122,"sourceCode":"            : this(tokenSource, 256)\n        {\n        }\n\n        public UnbufferedTokenStream(ITokenSource tokenSource, int bufferSize)\n        {\n            this.TokenSource = tokenSource;\n            this.tokens = new IToken[bufferSize];\n            n = 0;\n            Fill(1);\n        }\n\n        // prime the pump\n        public virtual IToken Get(int i)\n        {\n            int bufferStartIndex = GetBufferStartIndex();\n            if (i < bufferStartIndex || i >= bufferStartIndex + n)\n            {\n                throw new ArgumentOutOfRangeException(\"get(\" + i + \") outside buffer: \" + bufferStartIndex + \"..\" + (bufferStartIndex + n));\n            }\n            return tokens[i - bufferStartIndex];\n        }\n\n        public virtual IToken LT(int i)\n        {\n            if (i == -1)\n            {\n                return lastToken;\n            }\n            Sync(i);\n            int index = p + i - 1;\n            if (index < 0)\n            {\n                throw new ArgumentOutOfRangeException(\"LT(\" + i + \") gives negative index\");\n            }\n            if (index >= n)\n            {","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/CSharp/src/UnbufferedTokenStream.cs#L104-L140","documentation":"UnbufferedTokenStream stores tokens in a rolling buffer. Get(i) performs random access only inside that current buffer; an absolute token index before the buffer start or at/after buffer start plus count is outside the retained window and throws ArgumentOutOfRangeException.","triggerScenarios":"Calling Get(index) for already flushed tokens; requesting an absolute token index before the stream has synchronized/filled that far; or reusing an index after the buffer advanced.","commonSituations":"Token-inspection utilities written for BufferedTokenStream; rewrite/listener phases that index old tokens; debugging code that jumps to token numbers; or early EOF with indexes assumed to exist.","solutions":["Use relative access such as LT(k) when streaming.","Call Get only while the token remains in the current buffer and only after sufficient fill.","Use BufferedTokenStream when arbitrary token indexing is required."],"exampleFix":"// before\nIToken t = unbuffered.Get(0); // after buffer advanced\n\n// after\nvar tokens = new BufferedTokenStream(lexer);\ntokens.Fill();\nIToken t = tokens.Get(0);","handlingStrategy":"type-guard","validationCode":"if (tokens is UnbufferedTokenStream)\n    throw new InvalidOperationException(\"Random token access requires BufferedTokenStream.\");","typeGuard":"static bool SupportsRandomTokenAccess(ITokenStream stream) => stream is not UnbufferedTokenStream;","tryCatchPattern":"try { var t = tokens.Get(i); }\ncatch (ArgumentOutOfRangeException ex) when (ex.Message.StartsWith(\"get(\")) { /* use LT(k) or BufferedTokenStream */ }","preventionTips":["Use LT(k), not absolute Get(i), while streaming.","Call Get only after ensuring the index is currently buffered.","Use BufferedTokenStream for token inspection tools."],"tags":["antlr","csharp","token-stream","streaming","random-access"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}