oracle/graal · error · UnsupportedRegexException
possessive quantifiers are not supported
Error message
possessive quantifiers are not supported
What it means
The same possessive-quantifier rejection as in the parser, raised from the JavaRegexValidator pass. TRegex validates the token stream before compilation; when a Quantifier token has isPossessive() set, the validator throws UnsupportedRegexException('possessive quantifiers are not supported') even in contexts where the parser's own check did not fire (e.g. dangling or validator-only paths).
Source
Thrown at regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/flavor/java/JavaRegexValidator.java:126
case wordBoundary:
case nonWordBoundary:
case charClass:
case classSet:
case linebreak:
case backReference:
curTermState = CurTermState.Other;
break;
case quantifier:
Token.Quantifier quantifier = (Token.Quantifier) token;
// quantifiers of type *, + or ? cannot directly follow another quantifier
if (last instanceof Token.Quantifier && quantifier.isSingleChar()) {
throw syntaxErrorHere(JavaErrorMessages.danglingMetaCharacter(quantifier), ErrorCode.InvalidQuantifier);
}
if (curTermState == CurTermState.Null && quantifier.isSingleChar()) {
throw syntaxErrorHere(JavaErrorMessages.danglingMetaCharacter(quantifier), ErrorCode.InvalidQuantifier);
}
if (quantifier.isPossessive()) {
throw new UnsupportedRegexException("possessive quantifiers are not supported");
}
break;
case alternation:
case inlineFlags:
curTermState = CurTermState.Null;
break;
case captureGroupBegin:
case nonCaptureGroupBegin:
curTermState = CurTermState.Null;
syntaxStack.add(RegexStackElem.Group);
break;
case lookAheadAssertionBegin:
curTermState = CurTermState.Null;
syntaxStack.add(RegexStackElem.LookAheadAssertion);
break;
case lookBehindAssertionBegin:
curTermState = CurTermState.Null;
syntaxStack.add(RegexStackElem.LookBehindAssertion);View on GitHub (pinned to a66e9ccd1d)
Solutions
- Remove the possessive '+' from every quantifier in the pattern ('a?+' -> 'a?', '(ab){1,3}+' -> '(ab){1,3}')
- Grep patterns for the possessive suffix regex ([*+?}]|\{[0-9]+(,[0-9]*)?\})\+ before compiling when patterns are externally supplied
- If cut semantics are required, compute them outside the regex or switch to java.util.regex for that pattern
Example fix
// before String p = "x?+y"; // after String p = "x?y";
Defensive patterns
Strategy: validation
Validate before calling
private static final java.util.regex.Pattern POSSESSIVE =
java.util.regex.Pattern.compile("([*+?]|\\{[0-9]+(,[0-9]*)?\\})\\+");
boolean hasPossessiveQuantifier(String pattern) {
return POSSESSIVE.matcher(pattern).find();
} Try / catch
try {
RegexObject re = compileJavaFlavor(pattern);
} catch (UnsupportedRegexException e) {
if (e.getReason().contains("possessive")) {
pattern = POSSESSIVE.matcher(pattern).replaceAll("$1");
re = compileJavaFlavor(pattern);
} else { throw e; }
} Prevention
- Validate the token stream (or string) for possessive suffixes before the validator pass rejects it
- Keep a pattern sanitizer at your API boundary for user-supplied regexes
When it happens
Trigger: Any Java-flavor pattern containing *+, ++, ?+ or {n,m}+ that reaches the validation stage, e.g. validating "x?+" after parse; the validator's quantifier case calls quantifier.isPossessive() and throws.
Common situations: Same as the parser variant: JDK-optimized or ReDoS-hardened patterns with possessive quantifiers run on a TRegex-backed engine; users see either this validator message or the parser's depending on which pass encounters the token first.
Related errors
- possessive quantifiers are not supported
- Extended grapheme cluster boundaries are not supported
- Grapheme clusters are not supported
- End of previous match boundary matcher is not supported
- Literal escape not supported in this context
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/21bd7e38c6158f37.
Report an issue: GitHub.