oracle/graal · error · UnsupportedRegexException
Canonical equivalence is not supported
Error message
Canonical equivalence is not supported
What it means
The java.util.regex-flavored lexer (JavaRegexLexer) rejects Pattern.CANON_EQ at construction time by throwing UnsupportedRegexException: TRegex does not implement canonical equivalence decomposition, so patterns compiled with that flag cannot be translated.
Source
Thrown at regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/flavor/java/JavaRegexLexer.java:152
return Token.createCharClass(curCharClass.toCodePointSet());
} else {
return Token.createCharClass(CodePointSet.create(codePoint));
}
}
private static final TBitSet WHITESPACE = TBitSet.valueOf('\t', '\n', '\f', '\r', ' ');
private static final TBitSet PREDEFINED_CHAR_CLASSES = TBitSet.valueOf('D', 'H', 'S', 'V', 'W', 'd', 'h', 's', 'v', 'w');
private static final TBitSet LATIN1_CHARS_THAT_CASE_FOLD_TO_NON_LATIN1_CHARS = TBitSet.valueOf(0x49, 0x4b, 0x53, 0x69, 0x6b, 0x73, 0xb5, 0xc5, 0xe5, 0xff);
final JavaUnicodeProperties unicode;
private final Deque<JavaFlags> flagsStack = new ArrayDeque<>();
private JavaFlags currentFlags;
private final CodePointSetAccumulator curCharClass = new CodePointSetAccumulator();
public JavaRegexLexer(RegexSource source, JavaFlags flags, CompilationBuffer compilationBuffer) {
super(source, compilationBuffer);
if (flags.isCanonEq()) {
throw new UnsupportedRegexException("Canonical equivalence is not supported");
}
if (flags.isLiteral()) {
throw new UnsupportedRegexException("Literal parsing is not supported");
}
this.unicode = JavaUnicodeProperties.create(source.getOptions());
this.currentFlags = flags;
}
@Override
protected boolean isPredefCharClass(char c) {
return PREDEFINED_CHAR_CLASSES.get(c);
}
JavaFlags getLocalFlags() {
return currentFlags;
}
public void pushLocalFlags() {View on GitHub (pinned to a66e9ccd1d)
Solutions
- Remove the CANON_EQ flag if your input is already normalized (NFC/NFD) beforehand — usually sufficient.
- Pre-normalize both pattern and input with java.text.Normalizer and match without CANON_EQ.
- If canonical equivalence is mandatory, execute that match with a fallback regex engine that supports it.
Example fix
// before
Pattern p = Pattern.compile("a\u0300", Pattern.CANON_EQ); // throws on TRegex
// after
String pat = Normalizer.normalize("a\u0300", Form.NFC); // "\u00E0"
Pattern p = Pattern.compile(Pattern.quote(pat)); // match NFC-normalized input Defensive patterns
Strategy: fallback
Validate before calling
int flags = ...;
boolean needsCanonEq = (flags & Pattern.CANON_EQ) != 0;
if (needsCanonEq) {
// normalize inputs instead of relying on CANON_EQ
pattern = Normalizer.normalize(pattern, Normalizer.Form.NFC);
input = Normalizer.normalize(input, Normalizer.Form.NFC);
flags &= ~Pattern.CANON_EQ;
} Try / catch
try {
return Pattern.compile(pattern, flags);
} catch (com.oracle.truffle.regex.UnsupportedRegexException e) {
if ((flags & Pattern.CANON_EQ) != 0) {
return compileWithHostFallback(pattern, flags); // route to engine supporting CANON_EQ
}
throw e;
} Prevention
- Normalize pattern and input to NFC and drop CANON_EQ — equivalent for NFC data.
- Audit dependencies for unconditional Pattern.CANON_EQ use before running on GraalVM.
- Wrap regex compilation in a policy layer so unsupported flags can fall back gracefully.
When it happens
Trigger: Compiling a regex through the JavaUtilPattern flavor with Pattern.CANON_EQ set, e.g. Pattern.compile(pattern, Pattern.CANON_EQ) executed on Espresso, or a library (e.g. text normalization utilities) that always passes CANON_EQ.
Common situations: Libraries written for HotSpot that use CANON_EQ for Unicode text matching run on GraalVM/Espresso; security or text-processing code assuming full java.util.regex feature parity.
Related errors
- Literal parsing is not supported
- Syntax '{}' not recognized
- Path component is undefined
- Path component should be '/'
- Query component present
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/4861fb38a6e9841b.
Report an issue: GitHub.