stanfordnlp/CoreNLP · error · IllegalArgumentException

Illegal quantifier at beginning of pattern

Error message

Illegal quantifier at beginning of pattern: ${str}

What it means

Thrown while compiling a formatter pattern when a quantifier (e.g. digits or repetition syntax like '2' or '.') appears before any format component has been built. The pattern grammar requires at least one component before a quantifier can attach to it.

Solutions

  1. Fix the pattern so it begins with a format component (e.g. yyyy, dd, MM) before any quantifier.
  2. Check the pattern for truncation or stray leading digits/punctuation.
  3. Add a pre-compile regex sanity check on pattern strings loaded from config.

Example fix

// before
expr: "2dd/MM/yyyy"

// after
expr: "dd/MM/yyyy"
Defensive patterns

Strategy: validation

Validate before calling

static boolean patternStartsWithComponent(String p) {
  // must begin with a letter (format directive) not a quantifier/digit
  return p != null && p.matches("^[A-Za-z].*");
}

Try / catch

try {
  compilePattern(expr);
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Illegal quantifier at beginning")) {
    throw new IllegalArgumentException("Check formatter pattern for leading quantifier: " + expr, e);
  } else throw e;
}

Prevention

When it happens

Trigger: A rule formatter pattern that starts with a quantifier character, e.g. expr starting with a digit or repetition marker like "2dd/MM" instead of "dd/MM".

Common situations: Typos in .sutime.txt formatter patterns; accidentally truncating the pattern so only a quantifier remains; copy/paste dropping the first format letters.

Related errors


AI-assisted analysis of stanfordnlp/CoreNLP@1b7edd19c4 (2026-09-10). Data as JSON: /api/errors/af76bc5c7df8a6fe. Report an issue: GitHub.

Appendix: source

Thrown at src/edu/stanford/nlp/time/TimeFormatter.java:908

      appendComponent(new TimeZoneIdComponent(), true);
    }
    protected void appendTimeZoneName() {
      builder.appendTimeZoneName();
      // TODO: TimeZoneName
      appendComponent(new TimeZoneComponent(locale), true);
    }
    protected void appendTimeZoneShortName() {
      builder.appendTimeZoneShortName();
      // TODO: TimeZoneName
      appendComponent(new TimeZoneComponent(locale), true);
    }

    protected void appendQuantifier(String str) {
      if (pieces.size() > 0) {
        FormatComponent last = pieces.get(pieces.size() - 1);
        last.appendQuantifier(str);
      } else {
        throw new IllegalArgumentException("Illegal quantifier at beginning of pattern: " + str);
      }
    }

    protected void appendGroupStart() { appendRegexPart("(?:");}

    protected void appendGroupEnd() { appendRegexPart(")"); }

    protected void appendLiteral(char c) {
      builder.appendLiteral(c);
      appendLiteralField(String.valueOf(c));}

    protected void appendLiteral(String s) {
      builder.appendLiteral(s);
      appendLiteralField(s); }
  }

  private static void parsePatternTo(FormatterBuilder builder, String pattern) {
    int length = pattern.length();

View on GitHub (pinned to 1b7edd19c4)