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.

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.

Appendix: 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)