antlr/antlr4 · error · IllegalArgumentException
cannot seek to negative index {index}
Error message
cannot seek to negative index {index} What it means
UnbufferedCharStream.seek(index) computes the offset of index from the buffer start; a negative offset means the requested character position lies before the retained window, which an unbuffered stream cannot re-read. It throws IllegalArgumentException ('cannot seek to negative index') rather than silently re-reading discarded data.
Source
Thrown at runtime/Java/src/org/antlr/v4/runtime/UnbufferedCharStream.java:291
/** Seek to absolute character index, which might not be in the current
* sliding window. Move {@code p} to {@code index-bufferStartIndex}.
*/
@Override
public void seek(int index) {
if (index == currentCharIndex) {
return;
}
if (index > currentCharIndex) {
sync(index - currentCharIndex);
index = Math.min(index, getBufferStartIndex() + n - 1);
}
// index == to bufferStartIndex should set p to 0
int i = index - getBufferStartIndex();
if ( i < 0 ) {
throw new IllegalArgumentException("cannot seek to negative index " + index);
}
else if (i >= n) {
throw new UnsupportedOperationException("seek to index outside buffer: "+
index+" not in "+getBufferStartIndex()+".."+(getBufferStartIndex()+n));
}
p = i;
currentCharIndex = index;
if (p == 0) {
lastChar = lastCharBufferStart;
}
else {
lastChar = data[p-1];
}
}
@Override
public int size() {View on GitHub (pinned to 7d5770395b)
Solutions
- Hold a mark() across the region you may need to re-seek into, and release it only when done
- Extract the text you will need later (via getText) before the buffer moves past it
- Switch to a buffered stream (ANTLRInputStream / fromReader with buffering) if arbitrary backward seeks are required
Example fix
// before
// ... lex far ahead ...
stream.seek(0); // IllegalArgumentException: 0 < bufferStartIndex
// after
int m = stream.mark();
try {
// ... lex, then rewind safely ...
stream.seek(stream.index() ); // stay within marked window
} finally {
stream.release(m);
} Defensive patterns
Strategy: validation
Validate before calling
// bufferStartIndex == index() - (buffered count); track a floor via marks
int floor = markedFloorIndex; // recorded at mark() time
if (index < floor) {
throw new UnsupportedOperationException("target " + index + " was discarded; use a buffered stream");
}
stream.seek(index); Try / catch
try { stream.seek(target); }
catch (IllegalArgumentException | UnsupportedOperationException e) { /* re-open input in a buffered stream and retry the whole parse */ } Prevention
- Never seek backward in an unbuffered stream without a live mark
- Extract text before the window moves past it
- Use ANTLRInputStream when rewind semantics are needed
When it happens
Trigger: seek(0) or any backward seek after the buffer has advanced past the target (markers released, earlier chars discarded); seek to an index below the current bufferStartIndex after long forward consumption.
Common situations: Error reporting or token-highlighting code that rewinds to re-extract text after parsing has moved on; generic stream utilities that assume seek(0) is always legal; migrating code from ANTLRInputStream (buffered) to UnbufferedCharStream for memory reasons.
Related errors
- seek to index outside buffer: {index} not in {bufferStartInd
- release() called with an invalid marker.
- interval {interval} outside buffer: {bufferStartIndex}..{buf
- cannot seek to negative index ${index}
- seek to index outside buffer: ${index} not in ${bufferStartI
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/339c11501dfab319.
Report an issue: GitHub.