{"record":{"id":"6012a0d570237fed","repo":"elastic/elasticsearch","slug":"testresponse-not-paired-with-a-snippet-at","errorCode":null,"errorMessage":"TESTRESPONSE not paired with a snippet at ","messagePattern":"TESTRESPONSE not paired with a snippet at ","errorType":"validation","errorClass":"InvalidUserDataException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/doc/SnippetParser.java","lineNumber":146,"sourceCode":"    protected SnippetBuilder newSnippetBuilder() {\n        snippetBuilder = new SnippetBuilder().withPath(currentPath);\n        return snippetBuilder;\n    }\n\n    void fileParsingFinished(List<Snippet> snippets) {\n        if (snippetBuilder != null) {\n            snippets.add(snippetBuilder.build());\n            snippetBuilder = null;\n        }\n    }\n\n    protected abstract void parseLine(List<Snippet> snippets, int lineNumber, String line);\n\n    boolean testResponseHandled(String line, SnippetBuilder snippetBuilder) {\n        Matcher matcher = testResponsePattern().matcher(line);\n        if (matcher.matches()) {\n            if (snippetBuilder == null) {\n                throw new InvalidUserDataException(\"TESTRESPONSE not paired with a snippet at \");\n            }\n            snippetBuilder.withTestResponse(true);\n            if (matcher.group(2) != null) {\n                ParsingUtils.parse(\n                    matcher.group(2),\n                    \"(?:\" + SUBSTITUTION + \"|\" + NON_JSON + \"|\" + SKIP_REGEX + \") ?\",\n                    (Matcher m, Boolean last) -> {\n                        if (m.group(1) != null) {\n                            // TESTRESPONSE[s/adsf/jkl/]\n                            snippetBuilder.withSubstitution(m.group(1), m.group(2));\n                        } else if (m.group(3) != null) {\n                            // TESTRESPONSE[non_json]\n                            snippetBuilder.withSubstitution(\"^\", \"/\");\n                            snippetBuilder.withSubstitution(\"\\n$\", \"\\\\\\\\s*/\");\n                            snippetBuilder.withSubstitution(\"( +)\", \"$1\\\\\\\\s+\");\n                            snippetBuilder.withSubstitution(\"\\n\", \"\\\\\\\\s*\\n \");\n                        } else if (m.group(4) != null) {\n                            // TESTRESPONSE[skip:reason]","sourceCodeStart":128,"sourceCodeEnd":164,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/doc/SnippetParser.java#L128-L164","documentation":"Thrown by SnippetParser.testResponseHandled() when a line matching the TESTRESPONSE regex is encountered but there is no currently-open snippet (snippetBuilder == null). TESTRESPONSE markers are response assertions that must follow a CONSOLE snippet; a TESTRESPONSE with no preceding snippet has nothing to test against. Note the message ends with 'at ' but no location is appended, so the file:line comes only from the outer SnippetParserException wrapper (error 208).","triggerScenarios":"A documentation file contains a `// TESTRESPONSE[...]` line that is not preceded by a `// CONSOLE` snippet block (or the preceding snippet was already closed/finalized). The testResponsePattern matches, snippetBuilder is null, and the exception fires.","commonSituations":"A TESTRESPONSE block was separated from its CONSOLE snippet by editing (e.g. the CONSOLE block was deleted but the TESTRESPONSE left behind); the markers are in the wrong order; an extra blank-line or directive caused the parser to close the snippet before reaching TESTRESPONSE.","solutions":["Locate the `// TESTRESPONSE` line (use the file:line from the outer SnippetParserException) and ensure it directly follows the `// CONSOLE` snippet whose response it asserts.","If the CONSOLE snippet was removed intentionally, delete the orphaned TESTRESPONSE block as well.","Verify there is no stray snippet-closing directive between the CONSOLE block and the TESTRESPONSE."],"exampleFix":"// before:\n// TESTRESPONSE\n{ \"acknowledged\": true }\n// (no preceding CONSOLE)\n// after:\n// CONSOLE\nPUT /idx\n// TESTRESPONSE\n{ \"acknowledged\": true }","handlingStrategy":"validation","validationCode":"// Before building, walk doc lines and ensure every // TESTRESPONSE has a preceding open // CONSOLE snippet.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pair `// TESTRESPONSE` immediately after the `// CONSOLE` snippet it tests.","When deleting a CONSOLE block, delete its TESTRESPONSE too.","Avoid inserting directives between the snippet and its TESTRESPONSE."],"tags":["docs","snippet-tests","validation"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}