oracle/graal · error · UnsupportedRegexException
case-unfolding of case-insensitive string is too complex
Error message
case-unfolding of case-insensitive string is too complex
What it means
Thrown by MultiCharacterCaseFolding.unfoldSegment when the recursion depth of case-unfolding a case-insensitive string segment exceeds 12. To match case-insensitively against all foldings (e.g. 'ss' vs U+00DF, Greek sigma variants, ligatures), the parser enumerates reverse unfoldings with backtracking; segments whose alternatives multiply beyond depth 12 are rejected as too complex.
Source
Thrown at regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/MultiCharacterCaseFolding.java:171
private static List<Integer> caseFold(CaseFoldData.CaseFoldAlgorithm algorithm, int[] codepoints) {
List<Integer> caseFolded = new ArrayList<>();
for (int codepoint : codepoints) {
int[] folded = caseFold(algorithm, codepoint);
if (folded == null) {
caseFolded.add(codepoint);
} else {
for (int foldedElem : folded) {
caseFolded.add(foldedElem);
}
}
}
return caseFolded;
}
private static void unfoldSegment(CaseFoldData.CaseFoldAlgorithm algorithm, RegexASTBuilder astBuilder, ArrayList<OracleDBCharClassTrieNode> leafNodes, List<Integer> caseFolded,
List<Unfolding> unfoldings, int start, int end, int backtrackingDepth, boolean dropAsciiOnStart, boolean transitiveEquivalence, CompilationBuffer compilationBuffer) {
if (backtrackingDepth > 12) {
throw new UnsupportedRegexException("case-unfolding of case-insensitive string is too complex");
}
// The terminating condition of this recursion. This is reached when we have generated
// an alternative that covers the entire case-folded segment given by `start` and `end`.
if (start == end) {
return;
}
// This shouldn't happen in our current use case, but it's included for completeness.
if (unfoldings.isEmpty()) {
addString(astBuilder, leafNodes, caseFolded.subList(start, end), compilationBuffer);
return;
}
Unfolding unfolding = unfoldings.get(0);
// Fast-forward to the next possible unfolding.
if (unfolding.getStart() > start) {
addString(astBuilder, leafNodes, caseFolded.subList(start, unfolding.getStart()), compilationBuffer);
unfoldSegment(algorithm, astBuilder, leafNodes, caseFolded, unfoldings, unfolding.getStart(), end, backtrackingDepth, dropAsciiOnStart, transitiveEquivalence, compilationBuffer);
return;
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Shorten the literal run of fold-ambiguous characters, or split it so each segment has fewer consecutive folding alternatives.
- Restrict case-insensitivity to the ASCII part, or drop CASE_INSENSITIVE for that segment and normalize input case in application code instead.
- Match case-sensitively against pre-lowercased input (and pre-lowercased pattern) when full Unicode folding is not required.
Example fix
// before
Pattern p = Pattern.compile("\u00dfss\u00dfss\u00dfss", Pattern.CASE_INSENSITIVE); // deep unfolding
// after
Pattern p = Pattern.compile(Pattern.quote(input.toLowerCase()), Pattern.CASE_INSENSITIVE); // or match case-sensitively on normalized text Defensive patterns
Strategy: validation
Validate before calling
// count fold-ambiguous characters in case-insensitive literals before compiling
String foldProne = "s\u00df\u03c3\u03c2i\u0130k\u00f6"; long n = literal.chars().filter(c -> foldProne.indexOf(c) >= 0).count(); if (n > 12) throw new IllegalArgumentException("case-unfolding too complex"); Type guard
null
Try / catch
try { compileCaseInsensitive(pattern); } catch (UnsupportedRegexException e) { /* match case-sensitively on pre-normalized text instead */ } Prevention
- Normalize case of pattern and input yourself instead of CASE_INSENSITIVE for fold-heavy text.
- Shorten literal runs of fold-ambiguous characters.
- Restrict case-insensitive matching to ASCII ranges where possible.
When it happens
Trigger: Compiling a case-insensitive literal string (or string-containing character class, e.g. via \q{...} or set strings) that contains characters with many case-folding equivalences in close succession, e.g. long runs of 's', 'i', 'k', 'sigma' or ligature characters under CASE_INSENSITIVE (especially with Unicode case folding).
Common situations: Case-insensitive matching of German/Greek/Turkish text or ligature-rich input; flavor-specific string sets (OracleDB char-class tries) with case-insensitive flags; patterns generated from user text with many fold-prone letters in a row.
Related errors
- Class set expression maximum nesting level exceeded
- too many sequences in a single group
- too many terms in a single sequence
- too many capture groups
- Unsupported Unicode character property escape
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/be664496cdbc100d.
Report an issue: GitHub.