antlr/antlr4 · error · UnsupportedOperationException

interval {interval} outside buffer: {bufferStartIndex}..{buf

Error message

interval {interval} outside buffer: {bufferStartIndex}..{bufferStartIndex+n-1}

What it means

UnbufferedCharStream.getText(Interval) throws UnsupportedOperationException when any part of the requested interval lies outside the retained buffer window (interval.a < bufferStartIndex or interval.b >= bufferStartIndex + n). Characters before the window were already discarded and cannot be re-read; this is the unbuffered design trade-off, so it is unsupported rather than an invalid argument.

Source

Thrown at runtime/Java/src/org/antlr/v4/runtime/UnbufferedCharStream.java:336

		return name;
	}

	@Override
	public String getText(Interval interval) {
		if (interval.a < 0 || interval.b < interval.a - 1) {
			throw new IllegalArgumentException("invalid interval");
		}

		int bufferStartIndex = getBufferStartIndex();
		if (n > 0 && data[n - 1] == Character.MAX_VALUE) {
			if (interval.a + interval.length() > bufferStartIndex + n) {
				throw new IllegalArgumentException("the interval extends past the end of the stream");
			}
		}

		if (interval.a < bufferStartIndex || interval.b >= bufferStartIndex + n) {
			throw new UnsupportedOperationException("interval "+interval+" outside buffer: "+
			                    bufferStartIndex+".."+(bufferStartIndex+n-1));
		}
		// convert from absolute to local index
		int i = interval.a - bufferStartIndex;
		return new String(data, i, interval.length());
	}

	protected final int getBufferStartIndex() {
		return currentCharIndex - p;
	}
}

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Extract text eagerly during the parse (in enterRule/exitRule or via the lexer) while it is still inside the window
  2. Hold a mark() from before the earliest text you will need and release it after extraction
  3. Use a buffered stream (ANTLRInputStream/CharStreams.fromPath) if late text extraction is unavoidable

Example fix

// before
parser.buildParseTree = true;
new ParseTreeWalker().walk(listener, tree);
// listener later calls ctx.getText() -> chars already discarded -> throws

// after
// extract needed text during the parse:
class MyListener extends MyParserBaseListener {
    @Override public void exitEveryRule(ParserRuleContext ctx) {
        record(ctx, tokens.getText(ctx)); // while window still covers ctx
    }
}
Defensive patterns

Strategy: validation

Validate before calling

int bufferStart = /* track via marks, or compute as index() - p equivalent */ floorIndex;
if (interval.a < floorIndex) {
    text = previouslyExtracted.get(interval); // cache text eagerly during parse
} else {
    text = stream.getText(interval);
}

Try / catch

try { stream.getText(interval); }
catch (UnsupportedOperationException e) { /* fall back to cached text captured during the parse */ }

Prevention

When it happens

Trigger: Calling getText for a range parsed long ago after the window advanced (e.g., in a parse-tree listener or after parsing finishes); requesting text behind the current mark horizon; token text extraction deferred until after the parse.

Common situations: Post-parse tree walking that calls ctx.getText() or token text lookups on large inputs; error reporting that quotes earlier lines; switching from ANTLRInputStream to UnbufferedCharStream without auditing text lookups.

Related errors


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