{"record":{"id":"a4c8b0178da17abe","repo":"elastic/elasticsearch","slug":"snippet-wasn-t-first-testsetup-can-only-be-us","errorCode":null,"errorMessage":"${snippet}: wasn't first. TESTSETUP can only be used in the first snippet of a document.","messagePattern":"(.+?): wasn't first\\. TESTSETUP can only be used in the first snippet of a document\\.","errorType":"validation","errorClass":"InvalidUserDataException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/doc/RestTestsFromDocSnippetTask.java","lineNumber":453,"sourceCode":"\n            } else {\n                dest = dest.getParent().resolve(fileName.replace(\".asciidoc\", \".yml\").replace(\".mdx\", \".yml\"));\n\n            }\n\n            // Now setup the writer\n            try {\n                Files.createDirectories(dest.getParent());\n                current = new PrintWriter(dest.toFile(), StandardCharsets.UTF_8);\n                return current;\n            } catch (IOException e) {\n                throw new RuntimeException(e);\n            }\n        }\n\n        private void testSetup(Snippet snippet) {\n            if (lastDocsPath == snippet.path()) {\n                throw new InvalidUserDataException(\n                    snippet + \": wasn't first. TESTSETUP can only be used in the first snippet of a document.\"\n                );\n            }\n            setupCurrent(snippet);\n            current.println(\"---\");\n            current.println(\"setup:\");\n            if (snippet.setup() != null) {\n                setup(snippet);\n            }\n            body(snippet, true);\n        }\n\n        private void setup(final Snippet snippet) {\n            // insert a setup defined outside of the docs\n            for (final String name : snippet.setup().split(\",\")) {\n                final String setup = getSetups().get(name);\n                if (setup == null) {\n                    throw new InvalidUserDataException(\"Couldn't find named setup \" + name + \" for \" + snippet);","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/doc/RestTestsFromDocSnippetTask.java#L435-L471","documentation":"testSetup handles // TESTSETUP snippets. It checks if lastDocsPath == snippet.path() (reference equality on Path — effectively 'has a snippet from this file already been processed?'). If a snippet from the same file was already seen, this TESTSETUP is not the first snippet in the document, which violates the rule that setup must open the file. lastDocsPath is set only after setupCurrent processes the first snippet, so equality means an earlier snippet in this file preceded the setup.","triggerScenarios":"A // TESTSETUP snippet appears after another snippet (console request, response, etc.) in the same document file.","commonSituations":"Moving a TESTSETUP block down in the file below example requests; adding an introductory console example before the setup.","solutions":["Move the // TESTSETUP snippet to the very top of the document, before any other snippet.","If the setup logic is needed mid-file, convert it to a named setup registered in the build and reference it via // SETUP[name] on individual snippets instead."],"exampleFix":"// before — TESTSETUP after a request\n// CONSOLE\nGET /_search\n// TESTSETUP\nPOST /idx/_doc\n{ \"a\": 1 }\n\n// after — TESTSETUP first\n// TESTSETUP\nPOST /idx/_doc\n{ \"a\": 1 }\n// CONSOLE\nGET /_search","handlingStrategy":"validation","validationCode":"// Ensure // TESTSETUP is the first snippet in its file\nvoid checkTestSetupFirst(List<SnippetInfo> fileSnippets, String filePath) {\n    for (int i = 0; i < fileSnippets.size(); i++) {\n        if (fileSnippets.get(i).testSetup && i != 0) {\n            throw new IllegalStateException(\n                \"TESTSETUP in \" + filePath + \" must be the first snippet (at index \" + i + \")\");\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always put // TESTSETUP at the very top of the document file.","If setup logic is needed mid-file, use named setups (// SETUP[name]) on individual snippets instead.","After reordering snippets, verify TESTSETUP is still first."],"tags":["docs","testsetup","snippet","ordering","console"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}