antlr/antlr4 · error · NotSupportedException

interval not in token buffer window: ..

Error message

interval ${interval} not in token buffer window: ${bufferStartIndex}..${bufferStopIndex}

What it means

UnbufferedTokenStream.GetText(interval) can only render text for tokens still present in its fixed-size window; it throws NotSupportedException when interval.a < bufferStartIndex or interval.b > bufferStartIndex + tokens.Length - 1. Consumed tokens before the window are gone forever, and the window is only as large as the underlying token array.

Solutions

  1. Use CommonTokenStream when token text may be requested for arbitrary past intervals
  2. Capture GetText for a rule's interval inside its exit listener/listener callback, while the tokens are guaranteed still inside the window
  3. Before calling, verify interval.a >= GetBufferStartIndex() and interval.b <= bufferStartIndex + tokens.Length - 1, and skip or re-lex otherwise

Example fix

# before (Python-equivalent API usage pattern)
# tokens = UnbufferedTokenStream(lexer); parser error listener calls:
text = tokens.GetText(Interval(oldStart, oldStop))  # start already discarded

# after
text = None
if oldStart >= tokens.GetBufferStartIndex():
    text = tokens.GetText(Interval(oldStart, oldStop))
Defensive patterns

Strategy: validation

Validate before calling

// C#: verify the interval fits the current window before GetText
int bStart = stream.GetBufferStartIndex();
int bStop = bStart + stream.TokenSource... /* use your accessor for tokens.Length */;
if (interval.a >= bStart && interval.b <= bStop) {
    text = stream.GetText(interval);
}

Try / catch

try { text = stream.GetText(interval); } catch (NotSupportedException) { // interval partially outside the rolling window: emit a placeholder (e.g., '<unavailable text>') or re-lex the source range }

Prevention

When it happens

Trigger: Calling GetText() for a range that starts before GetBufferStartIndex() (already-discarded tokens) or ends past the window; error handlers requesting the text of a wide context interval; calling GetText on an interval captured from an earlier rule that has since been consumed.

Common situations: Syntax-error listeners or custom visitors that build message text from GetText(Interval) while using an unbuffered stream for memory efficiency; long-running parses where requested intervals drift outside the window; default error listeners that print offending-token text.

Related errors


AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14). Data as JSON: /api/errors/0fb1d564c21d7f0d. Report an issue: GitHub.

Appendix: source

Thrown at runtime/CSharp/src/UnbufferedTokenStream.cs:387

        public virtual string SourceName
        {
            get
            {
                return TokenSource.SourceName;
            }
        }

        [return: NotNull]
        public virtual string GetText(Interval interval)
        {
            int bufferStartIndex = GetBufferStartIndex();
            int bufferStopIndex = bufferStartIndex + tokens.Length - 1;
            int start = interval.a;
            int stop = interval.b;
            if (start < bufferStartIndex || stop > bufferStopIndex)
            {
                throw new NotSupportedException("interval " + interval + " not in token buffer window: " + bufferStartIndex + ".." + bufferStopIndex);
            }
            int a = start - bufferStartIndex;
            int b = stop - bufferStartIndex;
            StringBuilder buf = new StringBuilder();
            for (int i = a; i <= b; i++)
            {
                IToken t = tokens[i];
                buf.Append(t.Text);
            }
            return buf.ToString();
        }

        protected internal int GetBufferStartIndex()
        {
            return currentTokenIndex - p;
        }
    }
}

View on GitHub (pinned to 7d5770395b)