oracle/graal · error · UnsupportedRegexException

too many sequences in a single group

Error message

too many sequences in a single group

What it means

Thrown by Group.checkMaxSize when the number of alternatives (sequences) in a single group exceeds TRegexOptions.TRegexParserTreeMaxNumberOfSequencesInGroup (Short.MAX_VALUE = 32767). The AST stores alternatives in a list bounded so sequence indices stay short-representable; oversized alternations are rejected during parsing.

Source

Thrown at regex/src/com.oracle.truffle.regex/src/com/oracle/truffle/regex/tregex/parser/ast/Group.java:375

        sequence.setParent(this);
        alternatives.add(sequence);
        checkMaxSize();
    }

    /**
     * Inserts a new alternative to this group. The new alternative will be <em>inserted at the
     * beginning</em>, meaning it will have the <em>highest priority</em> among all the
     * alternatives.
     */
    public void insertFirst(Sequence sequence) {
        sequence.setParent(this);
        alternatives.add(0, sequence);
        checkMaxSize();
    }

    private void checkMaxSize() {
        if (alternatives.size() > TRegexOptions.TRegexParserTreeMaxNumberOfSequencesInGroup) {
            throw new UnsupportedRegexException("too many sequences in a single group");
        }
    }

    /**
     * Creates a new empty alternatives and adds it to the end of the list of alternatives.
     *
     * @param ast The AST that the new alternative should belong to
     * @return The newly created alternative
     */
    public Sequence addSequence(RegexAST ast) {
        Sequence sequence = ast.createSequence();
        add(sequence);
        return sequence;
    }

    public Sequence getLastAlternative() {
        return alternatives.get(size() - 1);
    }

View on GitHub (pinned to a66e9ccd1d)

Solutions

  1. Split the alternation into several regexes each below the cap and match them in a loop.
  2. Use a different data structure for keyword matching (Aho-Corasick automaton, a trie, or a HashSet of literals) instead of a giant regex.
  3. Factor common prefixes/suffixes of the alternatives to shrink the branch count.
  4. Warn in your generator when the branch count approaches 32767.

Example fix

// before
String pattern = words.stream().map(Pattern::quote).collect(Collectors.joining("|", "^(?:", ")$")); // one group
boolean m = Pattern.compile(pattern).matcher(s).matches();

// after
Set<String> set = Set.copyOf(words); // literal lookup, no regex
boolean m = set.contains(s); // or chunk into several patterns of <=10000 branches each
Defensive patterns

Strategy: validation

Validate before calling

int branches = pattern.split("\\|", -1).length - 1; if (branches > 32_000) throw new IllegalArgumentException("too many sequences in one group (max 32767)");

Type guard

null

Try / catch

try { compile(pattern); } catch (UnsupportedRegexException e) { if (e.getMessage().contains("too many sequences")) { /* split alternation into multiple patterns */ } }

Prevention

When it happens

Trigger: Compiling a single alternation group with more than 32767 branches, e.g. (word1|word2|...|word40000), typically from joining a large word list into one pattern.

Common situations: Dictionary/keyword matching built by String.join("|", words); blocklist/allowlist regexes generated from databases; incremental growth of a word list crossing the threshold after a data update.

Related errors


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