antlr/antlr4 · error · IndexOutOfBoundsException
start {} or stop {} not in 0..{}
Error message
start {} or stop {} not in 0..{} What it means
getTokens(int start, int stop, Set<Integer> types) requires both endpoints to lie inside the current token buffer (0..size()-1); otherwise it throws IndexOutOfBoundsException. Note the asymmetry with the two-argument get(start, stop), which returns null for negative bounds instead of throwing. lazyInit() runs first, but that only guarantees the first token exists, not that the whole range is fetched.
Source
Thrown at runtime/Java/src/org/antlr/v4/runtime/BufferedTokenStream.java:281
fetchedEOF = false;
}
public List<Token> getTokens() { return tokens; }
public List<Token> getTokens(int start, int stop) {
return getTokens(start, stop, null);
}
/** Given a start and stop index, return a List of all tokens in
* the token type BitSet. Return null if no tokens were found. This
* method looks at both on and off channel tokens.
*/
public List<Token> getTokens(int start, int stop, Set<Integer> types) {
lazyInit();
if ( start<0 || stop>=tokens.size() ||
stop<0 || start>=tokens.size() )
{
throw new IndexOutOfBoundsException("start "+start+" or stop "+stop+
" not in 0.."+(tokens.size()-1));
}
if ( start>stop ) return null;
// list = tokens[start:stop]:{T t, t.getType() in types}
List<Token> filteredTokens = new ArrayList<Token>();
for (int i=start; i<=stop; i++) {
Token t = tokens.get(i);
if ( types==null || types.contains(t.getType()) ) {
filteredTokens.add(t);
}
}
if ( filteredTokens.isEmpty() ) {
filteredTokens = null;
}
return filteredTokens;
}
View on GitHub (pinned to 7d5770395b)
Solutions
- Clamp: int stop = Math.min(stop, tokens.size() - 1) and reject start < 0 before calling
- Call tokens.fill() before ranged queries so size() reflects the whole input
- Return early (or null) yourself when start > stop or bounds are invalid instead of relying on the exception
Example fix
// before List<Token> all = tokens.getTokens(0, tokens.size(), types); // throws // after tokens.fill(); List<Token> all = tokens.getTokens(0, tokens.size() - 1, types);
Defensive patterns
Strategy: validation
Validate before calling
tokens.fill();
int stop = Math.min(requestedStop, tokens.size() - 1);
int start = Math.max(requestedStart, 0);
if (start <= stop) { List<Token> ts = tokens.getTokens(start, stop, types); } Prevention
- Clamp both endpoints into 0..size()-1 before calling getTokens
- Remember the 3-arg overload throws where the 2-arg overload returns null
- fill() first when querying ranges near the end of input
When it happens
Trigger: Calling getTokens(0, tokens.size(), null) (stop one past the end); passing stop from an unfilled stream's estimated size; passing -1 sentinels that the two-arg overload tolerates but this overload rejects.
Common situations: Filters over token types (e.g. collecting all comment or string tokens) written against the wrong overload's semantics; code migrated from get(start, stop) that relied on null returns for invalid ranges; highlighting code that clamps indices incorrectly.
Related errors
- token index {} out of range 0..{}
- {} not in 0..{}
- get({i}) outside buffer: {bufferStartIndex}..{bufferStartInd
- tokenSource cannot be null
- cannot consume EOF
AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14).
Data as JSON: /api/errors/54c3489949bca59d.
Report an issue: GitHub.