elastic/elasticsearch · error · InvalidUserDataException
// TEST[continued] cannot immediately follow // TESTSETUP: $
Error message
// TEST[continued] cannot immediately follow // TESTSETUP: ${test} What it means
Inside the test.continued() block, after verifying a same-file previousTest exists, the code checks if previousTest.testSetup() is true and throws this message. // TEST[continued] appends into the previous snippet's YAML test section, but a TESTSETUP snippet writes into the 'setup:' section — continuing from it would merge request steps into setup, which is invalid. NOTE: the source at line 247-248 checks testSetup() and labels it TESTSETUP; a near-identical check at line 250-251 (which throws the TEARDOWN message) also calls testSetup() rather than testTearDown(), which appears to be a copy-paste bug — the TEARDOWN branch likely intends to check testTearDown().
Source
Thrown at build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/doc/RestTestsFromDocSnippetTask.java:248
}
if (snippet.test() || snippet.language().equals("console")) {
test(snippet);
previousTest = snippet;
}
// Must be an unmarked snippet....
}
private void test(Snippet test) {
setupCurrent(test);
if (test.continued()) {
/* Catch some difficult to debug errors with // TEST[continued]
* and throw a helpful error message. */
if (previousTest == null || previousTest.path().equals(test.path()) == false) {
throw new InvalidUserDataException("// TEST[continued] " + "cannot be on first snippet in a file: " + test);
}
if (previousTest != null && previousTest.testSetup()) {
throw new InvalidUserDataException("// TEST[continued] " + "cannot immediately follow // TESTSETUP: " + test);
}
if (previousTest != null && previousTest.testSetup()) {
throw new InvalidUserDataException("// TEST[continued] " + "cannot immediately follow // TEARDOWN: " + test);
}
} else {
current.println("---");
if (test.name() != null && test.name().isBlank() == false) {
if (names.add(test.name()) == false) {
throw new InvalidUserDataException("Duplicated snippet name '" + test.name() + "': " + test);
}
current.println("\"" + test.name() + "\":");
} else {
current.println("\"line_" + test.start() + "\":");
}
/* The Elasticsearch test runner doesn't support quite a few
* constructs unless we output this skip. We don't know if
* we're going to use these constructs, but we might so we
* output the skip just in case. */View on GitHub (pinned to db6a809a66)
Solutions
- Insert a normal (non-continued, non-setup) console request snippet between the TESTSETUP and the // TEST[continued] snippet.
- Remove // TEST[continued] from the snippet if it should run as part of setup instead.
Example fix
// before — continued right after setup
// TESTSETUP
POST /idx/_doc
{ "a": 1 }
// CONSOLE
// TEST[continued]
GET /idx/_search
// after — base request separates them
// TESTSETUP
POST /idx/_doc
{ "a": 1 }
// CONSOLE
GET /idx/_search
// CONSOLE
// TEST[continued]
GET /idx/_search?q=a Defensive patterns
Strategy: validation
Validate before calling
// Ensure TEST[continued] does not immediately follow a TESTSETUP
void checkContinuedAfterSetup(List<SnippetInfo> fileSnippets, String filePath) {
for (int i = 1; i < fileSnippets.size(); i++) {
SnippetInfo prev = fileSnippets.get(i - 1);
SnippetInfo cur = fileSnippets.get(i);
if (cur.continued && prev.testSetup) {
throw new IllegalStateException(
"// TEST[continued] in " + filePath + " immediately follows TESTSETUP");
}
}
} Prevention
- Separate TESTSETUP and TEST[continued] with a normal base console request.
- Remember TESTSETUP writes into the 'setup:' section; a continued snippet cannot append there.
- When restructuring setup snippets, re-run the docs build to catch this ordering error.
When it happens
Trigger: A // TEST[continued] snippet immediately follows a // TESTSETUP snippet in the same file, so previousTest.testSetup() is true.
Common situations: Restructuring a doc so a TESTSETUP is the last snippet before a continued test; the continued test has no real base request to append to.
Related errors
- ${snippet}: No paired previous test
- // TEST[continued] cannot be on first snippet in a file: ${t
- // TEST[continued] cannot immediately follow // TEARDOWN: ${
- ${snippet}: wasn't first. TESTSETUP can only be used in the
- Extra content ${message} ('${cutOutNoNl}') matching [${patte
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/401c3fe677ea0016.
Report an issue: GitHub.