{"record":{"id":"d568ab76ef4a9264","repo":"elastic/elasticsearch","slug":"snippet-no-paired-previous-test","errorCode":null,"errorMessage":"${snippet}: No paired previous test","messagePattern":"(.+?): No paired previous test","errorType":"validation","errorClass":"InvalidUserDataException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/doc/RestTestsFromDocSnippetTask.java","lineNumber":220,"sourceCode":"            if (snippet.isConsoleCandidate()) {\n                unconvertedCandidates.add(snippet.path().toString().replace('\\\\', '/'));\n            }\n            if (BAD_LANGUAGES.contains(snippet.language())) {\n                throw new InvalidUserDataException(snippet + \": Use `js` instead of `\" + snippet.language() + \"`.\");\n            }\n            if (snippet.testSetup()) {\n                testSetup(snippet);\n                previousTest = snippet;\n                return;\n            }\n            if (snippet.testTearDown()) {\n                testTearDown(snippet);\n                previousTest = snippet;\n                return;\n            }\n            if (snippet.testResponse() || snippet.language().equals(\"console-result\")) {\n                if (previousTest == null) {\n                    throw new InvalidUserDataException(snippet + \": No paired previous test\");\n                }\n                if (previousTest.path().equals(snippet.path()) == false) {\n                    throw new InvalidUserDataException(snippet + \": Result can't be first in file\");\n                }\n                response(snippet);\n                return;\n            }\n            if ((\"js\".equals(snippet.language())) && snippet.console() != null && snippet.console()) {\n                throw new InvalidUserDataException(snippet + \": Use `[source,console]` instead of `// CONSOLE`.\");\n            }\n            if (snippet.test() || snippet.language().equals(\"console\")) {\n                test(snippet);\n                previousTest = snippet;\n            }\n            // Must be an unmarked snippet....\n        }\n\n        private void test(Snippet test) {","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/doc/RestTestsFromDocSnippetTask.java#L202-L238","documentation":"When a snippet is a test response (snippet.testResponse() true or language 'console-result'), handleSnippet expects a preceding non-response snippet (previousTest) to pair it with. previousTest is null only at the very start of the build before any test/setup/teardown snippet was seen. A response with no prior request has nothing to match against, so it throws.","triggerScenarios":"A document file's first snippet is a console-result / TESTRESPONSE block, or a TESTRESPONSE appears after a previous test that was in a different file and was not carried over — actually this specific branch (previousTest == null) fires only when no test snippet has been seen at all across the entire run up to this point.","commonSituations":"Reordering snippets in a doc file so a response block lands at the top, or splitting a file and leaving the response in the new file without its request. The more common cross-file case is caught by the separate 'Result can't be first in file' check.","solutions":["Move a console request snippet (// CONSOLE or [source,console]) above the response snippet in the same file.","If the response is orphaned, remove it or reattach it to its original request snippet."],"exampleFix":"// before — response with no preceding request\n// TESTRESPONSE\n{\"acknowledged\":true}\n\n// after — add the request first\n// CONSOLE\nPOST /_aliases\n{ \"actions\": [] }\n// TESTRESPONSE\n{\"acknowledged\":true}","handlingStrategy":"validation","validationCode":"// Ensure every TESTRESPONSE/console-result snippet has a preceding request in the same doc\n// (run as a pre-build docs lint over parsed snippets)\nvoid checkResponsesPaired(List<SnippetInfo> snippets) {\n    boolean seenRequest = false;\n    for (SnippetInfo s : snippets) {\n        if (s.isResponse) {\n            if (!seenRequest) {\n                throw new IllegalStateException(\n                    \"Response snippet \" + s.path + \" has no preceding request\");\n            }\n        } else if (s.isRequest) {\n            seenRequest = true;\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always write the console request snippet before its TESTRESPONSE block.","When splitting a doc file, move each request+response pair together.","Treat a TESTRESPONSE with no preceding request in the same file as a lint error."],"tags":["docs","snippet","test-response","console","testsetup"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}