oracle/graal · error · IllegalArgumentException

got illegal regionFrom value: %d. regionFrom must be >= 0 an

Error message

got illegal regionFrom value: %d. regionFrom must be >= 0 and <= input length (%d)

What it means

RegexExecNode is the Truffle regex engine's execution entry. In the 5-argument form (input, fromIndex, toIndex, regionFrom, regionTo) it validates the search region; regionFrom must be within [0, inputLength]. A negative regionFrom or one past the end of the input throws IllegalArgumentException.

Source

Thrown at regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexExecNode.java:85

        Object[] args = frame.getArguments();
        TruffleString.Encoding encoding = getEncoding().getTStringEncoding();
        CompilerAsserts.partialEvaluationConstant(encoding);
        TruffleString input = expectStringNode.execute(args[0], encoding);
        int length = InputOps.length(input, getEncoding());
        long fromIndex = toLongNode.execute(args[1]);
        if (fromIndex > Integer.MAX_VALUE) {
            return RegexResult.getNoMatchInstance();
        }
        final int toIndex;
        final int regionFrom;
        final int regionTo;
        if (args.length == 5) {
            long toIndexLong = toLongNode.execute(args[2]);
            long regionFromLong = toLongNode.execute(args[3]);
            long regionToLong = toLongNode.execute(args[4]);
            if (regionFromLong < 0 || regionFromLong > length) {
                CompilerDirectives.transferToInterpreterAndInvalidate();
                throw new IllegalArgumentException(String.format("got illegal regionFrom value: %d. regionFrom must be >= 0 and <= input length (%d)", regionFromLong, length));
            }
            if (regionToLong < regionFromLong || regionToLong > length) {
                CompilerDirectives.transferToInterpreterAndInvalidate();
                throw new IllegalArgumentException(String.format("got illegal regionTo value: %d. regionTo must be >= regionFrom (%d) and <= input length (%d)", regionToLong, regionFromLong, length));
            }
            if (fromIndex < regionFromLong || fromIndex > regionToLong) {
                CompilerDirectives.transferToInterpreterAndInvalidate();
                throw new IllegalArgumentException(
                                String.format("got illegal fromIndex value: %d. fromIndex must be >= regionFrom (%d) and <= regionTo (%d)", fromIndex, regionFromLong, regionToLong));
            }
            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));
            }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Clamp regionFrom to Math.max(0, Math.min(regionFrom, inputLength)) before invoking the engine.
  2. Check that the region was computed against the same input string instance you pass as argument 1.
  3. Audit lastIndex/region propagation in your adapter for negative or stale values after failed matches.

Example fix

// before
Object res = exec(in, start, end, regionFrom, regionTo); // regionFrom may be -1

// after
int rf = Math.max(0, Math.min((int) regionFrom, input.length()));
Object res = exec(in, start, end, rf, regionTo);
Defensive patterns

Strategy: validation

Validate before calling

static boolean validRegionFrom(long regionFrom, int inputLength) {
    return regionFrom >= 0 && regionFrom <= inputLength;
}

Prevention

When it happens

Trigger: Calling the TRegex builtin/foreign function with 5 args where the 4th argument (regionFrom) is negative or greater than the input string length, e.g. regionFrom = input.length() + 1 or regionFrom = -1.

Common situations: Guest-language adapters (GraalJS, FastR, Python on GraalVM) mapping native regex APIs with region parameters; off-by-one bugs where callers pass a region computed against a different string than the one matched; lastIndex bookkeeping bugs.

Related errors


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/7e3d96e4c901455c. Report an issue: GitHub.