elastic/elasticsearch · error · IllegalArgumentException

pattern [{}] has an invalid syntax

Error message

pattern [{}] has an invalid syntax

What it means

Thrown while expanding pattern references during cycle detection. getPatternNamesForPattern scans each pattern for %{ tokens; if it finds a %{ with no following } or : it cannot determine the referenced name and rejects the pattern as syntactically malformed. This guards against unterminated grok substitution markers before any matching is attempted.

Source

Thrown at libs/grok/src/main/java/org/elasticsearch/grok/PatternBank.java:174

     * are found, an empty array is returned. If any of the list of pattern names to be returned does not exist in the bank, an exception
     * is thrown.
     */
    private static String[] getPatternNamesForPattern(Map<String, String> bank, String patternName) {
        String pattern = bank.get(patternName);
        List<String> patternReferences = new ArrayList<>();
        for (int i = pattern.indexOf("%{"); i != -1; i = pattern.indexOf("%{", i + 1)) {
            int begin = i + 2;
            int bracketIndex = pattern.indexOf('}', begin);
            int columnIndex = pattern.indexOf(':', begin);
            int end;
            if (bracketIndex != -1 && columnIndex == -1) {
                end = bracketIndex;
            } else if (columnIndex != -1 && bracketIndex == -1) {
                end = columnIndex;
            } else if (bracketIndex != -1) {
                end = Math.min(bracketIndex, columnIndex);
            } else {
                throw new IllegalArgumentException("pattern [" + pattern + "] has an invalid syntax");
            }
            String otherPatternName = pattern.substring(begin, end);
            if (patternReferences.contains(otherPatternName) == false) {
                patternReferences.add(otherPatternName);
                String otherPattern = bank.get(otherPatternName);
                if (otherPattern == null) {
                    throw new IllegalArgumentException(
                        "pattern [" + patternName + "] is referencing a non-existent pattern [" + otherPatternName + "]"
                    );
                }
            }
        }
        return patternReferences.toArray(new String[0]);
    }
}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Open the named pattern shown in the message and find the %{ that has no matching } or : before the next %{ or end of string.
  2. Close the reference (%{NAME}) or convert the literal %{ into a regex-escaped form if it was not meant as a substitution.
  3. Validate patterns with a quick check (every %{ is followed by a } or :) before passing them to PatternBank.

Example fix

// before
Map<String,String> patterns = Map.of(
    "BAD", "time=%{TIMESTAMP ms" // missing closing }");
new PatternBank(patterns); // throws: pattern [...] has an invalid syntax

// after
Map<String,String> patterns = Map.of(
    "BAD", "time=%{TIMESTAMP:ms}");
new PatternBank(patterns); // ok
Defensive patterns

Strategy: validation

Validate before calling

// Reject patterns with unterminated %{ references before building the bank.
static boolean syntaxOk(java.util.Map<String,String> patterns) {
    java.util.regex.Pattern unterminated =
        java.util.regex.Pattern.compile("%\\{[^}]*$"); // %{ with no } before end-of-line
    for (var e : patterns.entrySet()) {
        if (unterminated.matcher(e.getValue()).find()) return false;
        // also reject %{ with neither } nor : after it on the same line
        java.util.regex.Matcher m = java.util.regex.Pattern.compile("%\\{([^}:])*").matcher(e.getValue());
        // (full validation mirrors PatternBank; simplest is to try-construct)
    }
    return true;
}

Try / catch

try {
    PatternBank bank = new PatternBank(patterns);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("has an invalid syntax")) {
        reportConfigError("malformed grok pattern: " + e.getMessage());
    } else throw e;
}

Prevention

When it happens

Trigger: Constructing a PatternBank whose map contains a value with an unterminated reference, e.g. "FOO": "prefix %{BAR more text" (no closing brace) or a lone "%{" in a pattern body. The parser found %{ but indexOf('}') and indexOf(':') after it both returned -1.

Common situations: Hand-editing a grok pattern and deleting the closing brace; a regex that legitimately needs a literal %{ without intending a substitution (must escape or restructure); truncated/copy-pasted pattern files missing the tail of a line.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/b55176cfe3ba8d8a. Report an issue: GitHub.