oracle/graal · error · IllegalArgumentException
got illegal fromIndex value: %d. fromIndex must be >= 0 and
Error message
got illegal fromIndex value: %d. fromIndex must be >= 0 and <= input length (%d)
What it means
In the 2-argument form (input, fromIndex), RegexExecNode defaults region to the whole string and only validates fromIndex; it must be within [0, inputLength]. A negative start index or one past the end throws IllegalArgumentException.
Source
Thrown at regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexExecNode.java:114
if (toIndexLong < fromIndex || toIndexLong > regionToLong) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new IllegalArgumentException(String.format("got illegal toIndex value: %d. toIndex must be >= fromIndex (%d) and <= regionTo (%d)", toIndexLong, fromIndex, regionToLong));
}
if (toIndexLong != regionToLong) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new UnsupportedOperationException(String.format("got non-equal toIndex (%d) and regionTo (%d), support for this is not implemented yet", toIndexLong, regionToLong));
}
toIndex = (int) toIndexLong;
regionFrom = (int) regionFromLong;
regionTo = (int) regionToLong;
} else {
assert args.length == 2;
toIndex = length;
regionFrom = 0;
regionTo = length;
if (fromIndex < 0 || fromIndex > length) {
CompilerDirectives.transferToInterpreterAndInvalidate();
throw new IllegalArgumentException(String.format("got illegal fromIndex value: %d. fromIndex must be >= 0 and <= input length (%d)", fromIndex, length));
}
}
return execute(frame, input, adjustFromIndex(input, (int) fromIndex, regionFrom, regionTo), toIndex, regionFrom, regionTo);
}
private int adjustFromIndex(TruffleString input, int fromIndex, int regionFrom, int regionTo) {
if (mustCheckUTF16Surrogates && fromIndex > regionFrom && fromIndex < regionTo) {
assert getEncoding().isUTF16();
if (Character.isLowSurrogate((char) inputRead(input, fromIndex)) && Character.isHighSurrogate((char) inputRead(input, fromIndex - 1))) {
return fromIndex - 1;
}
}
return fromIndex;
}
public final int inputRead(TruffleString input, int i) {
if (charAtNode == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();View on GitHub (pinned to a66e9ccd1d)
Solutions
- Clamp fromIndex: fromIndex = Math.max(0, Math.min(fromIndex, inputLength)).
- Initialize and reset lastIndex to 0 for each new input string.
- When converting code-point indices to UTF-16 indices, re-check the bound against the actual string length.
Example fix
// before if (m.find()) idx = m.end(); ... exec(input, idx); // idx may exceed new input's length // after idx = Math.max(0, Math.min(idx, input.length())); exec(input, idx);
Defensive patterns
Strategy: validation
Validate before calling
static boolean validFromIndex2Arg(long fromIndex, int inputLength) {
return fromIndex >= 0 && fromIndex <= inputLength;
} Prevention
- Initialize search-loop indices to 0, not -1.
- Clamp carried-over indices against the current input length before each exec.
- When working in code points, convert to UTF-16 indices and re-check bounds.
When it happens
Trigger: Calling the 2-arg regex exec with fromIndex < 0 (e.g. an uninitialized -1 'last match end') or fromIndex > input.length() (e.g. start index carried over from a longer previous input).
Common situations: Search loops that keep a nextIndex variable initialized to -1 and forget to reset it to 0; passing UTF-16 index computed on a differently encoded string whose code-point length exceeds UTF-16 length.
Related errors
- got illegal regionFrom value: %d. regionFrom must be >= 0 an
- got illegal regionTo value: %d. regionTo must be >= regionFr
- got illegal fromIndex value: %d. fromIndex must be >= region
- got illegal toIndex value: %d. toIndex must be >= fromIndex
- got non-equal toIndex (%d) and regionTo (%d), support for th
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/f7acb2a2f2078306.
Report an issue: GitHub.