{"record":{"id":"4801e71a77fc9d20","repo":"oracle/graal","slug":"got-illegal-fromindex-value-d-fromindex-must-be","errorCode":null,"errorMessage":"got illegal fromIndex value: %d. fromIndex must be >= regionFrom (%d) and <= regionTo (%d)","messagePattern":"got illegal fromIndex value: (.+?)\\. fromIndex must be >= regionFrom \\((.+?)\\) and <= regionTo \\((.+?)\\)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexExecNode.java","lineNumber":93,"sourceCode":"        }\n        final int toIndex;\n        final int regionFrom;\n        final int regionTo;\n        if (args.length == 5) {\n            long toIndexLong = toLongNode.execute(args[2]);\n            long regionFromLong = toLongNode.execute(args[3]);\n            long regionToLong = toLongNode.execute(args[4]);\n            if (regionFromLong < 0 || regionFromLong > length) {\n                CompilerDirectives.transferToInterpreterAndInvalidate();\n                throw new IllegalArgumentException(String.format(\"got illegal regionFrom value: %d. regionFrom must be >= 0 and <= input length (%d)\", regionFromLong, length));\n            }\n            if (regionToLong < regionFromLong || regionToLong > length) {\n                CompilerDirectives.transferToInterpreterAndInvalidate();\n                throw new IllegalArgumentException(String.format(\"got illegal regionTo value: %d. regionTo must be >= regionFrom (%d) and <= input length (%d)\", regionToLong, regionFromLong, length));\n            }\n            if (fromIndex < regionFromLong || fromIndex > regionToLong) {\n                CompilerDirectives.transferToInterpreterAndInvalidate();\n                throw new IllegalArgumentException(\n                                String.format(\"got illegal fromIndex value: %d. fromIndex must be >= regionFrom (%d) and <= regionTo (%d)\", fromIndex, regionFromLong, regionToLong));\n            }\n            if (toIndexLong < fromIndex || toIndexLong > regionToLong) {\n                CompilerDirectives.transferToInterpreterAndInvalidate();\n                throw new IllegalArgumentException(String.format(\"got illegal toIndex value: %d. toIndex must be >= fromIndex (%d) and <= regionTo (%d)\", toIndexLong, fromIndex, regionToLong));\n            }\n            if (toIndexLong != regionToLong) {\n                CompilerDirectives.transferToInterpreterAndInvalidate();\n                throw new UnsupportedOperationException(String.format(\"got non-equal toIndex (%d) and regionTo (%d), support for this is not implemented yet\", toIndexLong, regionToLong));\n            }\n            toIndex = (int) toIndexLong;\n            regionFrom = (int) regionFromLong;\n            regionTo = (int) regionToLong;\n        } else {\n            assert args.length == 2;\n            toIndex = length;\n            regionFrom = 0;\n            regionTo = length;","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/RegexExecNode.java#L75-L111","documentation":"In RegexExecNode's 5-argument form, the search start index fromIndex must lie inside the declared region: regionFrom <= fromIndex <= regionTo. An out-of-region fromIndex throws IllegalArgumentException.","triggerScenarios":"Calling 5-arg exec with fromIndex < regionFrom or fromIndex > regionTo, e.g. fromIndex=0 with regionFrom=5, or fromIndex=input.length() while regionTo is smaller.","commonSituations":"Reusing a lastIndex from an unbounded search together with a narrowed region (e.g. emulating Matcher.region().find(lastIndex)); adapters that pass the string offset as fromIndex while the engine expects a region-relative start.","solutions":["Clamp fromIndex into the region: fromIndex = Math.max(regionFrom, Math.min(fromIndex, regionTo)).","Reset lastIndex/nextSearchIndex to regionFrom whenever a region is applied.","Double-check whether your API contract treats fromIndex as absolute or region-relative and convert accordingly."],"exampleFix":"// before\nexec(input, lastIndex, regionTo, regionFrom, regionTo); // lastIndex may be < regionFrom\n\n// after\nlastIndex = Math.max(regionFrom, Math.min(lastIndex, regionTo));\nexec(input, lastIndex, regionTo, regionFrom, regionTo);","handlingStrategy":"validation","validationCode":"static boolean validFromIndex(long fromIndex, long regionFrom, long regionTo) {\n    return fromIndex >= regionFrom && fromIndex <= regionTo;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reset the search start index to regionFrom whenever a region is applied.","Clamp fromIndex into [regionFrom, regionTo] before invoking exec.","Document clearly whether your API's start index is absolute or region-relative."],"tags":["regex","truffle","graalvm","argument-validation","region"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}