elastic/elasticsearch · error · InvalidUserDataException

Didn't match ${pattern}: ${content}

Error message

Didn't match ${pattern}: ${content}

What it means

ParsingUtils.parse compiles the pattern against the content and enters the match loop. If offset stays 0 after the loop, no match was found at all — the entire snippet content failed to match the CONSOLE syntax grammar even once. This is distinct from extra_content (partial match) because here the regex matched nothing.

Source

Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/doc/ParsingUtils.java:49

     * matchers each time there is a match. If there are characters that don't
     * match then blow up. If the closure takes two parameters then the second
     * one is "is this the last match?".
     */
    static void parse(String content, String pattern, BiConsumer<Matcher, Boolean> testHandler) {
        if (content == null) {
            return; // Silly null, only real stuff gets to match!
        }
        Matcher m = Pattern.compile(pattern).matcher(content);
        int offset = 0;
        while (m.find()) {
            if (m.start() != offset) {
                extraContent("between [$offset] and [${m.start()}]", content, offset, pattern);
            }
            offset = m.end();
            testHandler.accept(m, offset == content.length());
        }
        if (offset == 0) {
            throw new InvalidUserDataException("Didn't match " + pattern + ": " + content);
        }
        if (offset != content.length()) {
            extraContent("after [" + offset + "]", content, offset, pattern);
        }
    }

}

View on GitHub (pinned to db6a809a66)

Solutions

  1. Check the content shown in the message and add at least one valid request line (e.g. 'GET /_search').
  2. If the snippet should be empty/non-executable, mark it with the appropriate snippet attribute (e.g. // NOTCONSOLE) instead of leaving it as a console test.
  3. Verify the snippet opening delimiter in the asciidoc/mdx source is correct so content is actually captured.

Example fix

// before — empty console snippet produces no match
// CONSOLE

// after — add a valid request
// CONSOLE
GET /_cluster/health
Defensive patterns

Strategy: validation

Validate before calling

// Ensure every console snippet has at least one parseable request
import java.util.regex.Pattern;

private static final Pattern HAS_REQUEST = Pattern.compile(
    "(GET|PUT|POST|HEAD|OPTIONS|DELETE)\\s+\\S+|#|startyaml");

void checkNonEmptyConsole(String contents, String snippetPath) {
    if (!HAS_REQUEST.matcher(contents).find()) {
        throw new IllegalStateException(
            "Console snippet in " + snippetPath + " has no valid request, comment, or yaml block: "
            + contents);
    }
}

Prevention

When it happens

Trigger: A snippet marked as a test (// CONSOLE or console language) has a body that contains zero valid HTTP request lines, comments, or yaml blocks — e.g. an empty snippet body, or a body containing only text that none of the method/path/yaml/comment alternatives can match.

Common situations: An empty console snippet, a snippet where the opening line uses a method not in the allowed set (GET|PUT|POST|HEAD|OPTIONS|DELETE), or a snippet whose content was accidentally cleared during editing.

Related errors


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