antlr/antlr4 · error · IllegalArgumentException

invalid interval

Error message

invalid interval

What it means

UnbufferedCharStream.getText(Interval) first validates the interval itself: interval.a must be >= 0 and interval.b must be at least a-1 (an empty interval starting at a is legal). Any negative start or end more than one before the start is rejected as 'invalid interval' with IllegalArgumentException.

Source

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

    @Override
    public int size() {
        throw new UnsupportedOperationException("Unbuffered stream cannot know its size");
    }

    @Override
    public String getSourceName() {
		if (name == null || name.isEmpty()) {
			return UNKNOWN_SOURCE_NAME;
		}

		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());
	}

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Normalize the interval before calling: a >= 0 and b = Math.max(b, a - 1)
  2. Skip text extraction for contexts whose start/stop tokens are EOF or have negative indexes
  3. Build intervals from real matched tokens (ctx.start, ctx.stop) and null-check them

Example fix

// before
String t = stream.getText(Interval.of(ctx.start.getStartIndex(), ctx.stop.getStartIndex())); // EOF: -1,-1

// after
if (ctx.start == null || ctx.stop == null
        || ctx.start.getStartIndex() < 0 || ctx.stop.getStartIndex() < ctx.start.getStartIndex() - 1) {
    return "";
}
String t = stream.getText(Interval.of(ctx.start.getStartIndex(), ctx.stop.getStartIndex()));
Defensive patterns

Strategy: validation

Validate before calling

static Interval normalize(int a, int b) {
    if (a < 0) return null; // invalid
    return Interval.of(a, Math.max(b, a - 1));
}
Interval iv = normalize(start, stop);
if (iv != null) text = stream.getText(iv);

Prevention

When it happens

Trigger: getText(Interval.of(-1, -1)) or Interval.of(5, 2); intervals built from sentinel tokens whose getStartIndex()/getStopIndex() are -1 (EOF tokens); computing b as startIndex + length - 1 with a length that underflows.

Common situations: Extracting text for a rule context that matched only EOF; error listeners building intervals from invalid tokens; off-by-one arithmetic when constructing intervals from token positions.

Related errors


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