{"record":{"id":"0e2ede930064633a","repo":"elastic/elasticsearch","slug":"expected-unconverted-snippets-but-none-found-in","errorCode":null,"errorMessage":"Expected unconverted snippets but none found in:\n{listedButNotFound}","messagePattern":"Expected unconverted snippets but none found in:\n(.+?)","errorType":"validation","errorClass":"InvalidUserDataException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/doc/RestTestsFromDocSnippetTask.java","lineNumber":503,"sourceCode":"            String message = \"\";\n            if (false == listedButNotFound.isEmpty()) {\n                Collections.sort(listedButNotFound);\n                listedButNotFound = listedButNotFound.stream().map(notfound -> \"    \" + notfound).collect(Collectors.toList());\n                message += \"Expected unconverted snippets but none found in:\\n\";\n                message += listedButNotFound.stream().collect(Collectors.joining(\"\\n\"));\n            }\n            if (false == unconvertedCandidates.isEmpty()) {\n                List<String> foundButNotListed = new ArrayList<>(unconvertedCandidates);\n                Collections.sort(foundButNotListed);\n                foundButNotListed = foundButNotListed.stream().map(f -> \"    \" + f).collect(Collectors.toList());\n                if (false == \"\".equals(message)) {\n                    message += \"\\n\";\n                }\n                message += \"Unexpected unconverted snippets:\\n\";\n                message += foundButNotListed.stream().collect(Collectors.joining(\"\\n\"));\n            }\n            if (false == \"\".equals(message)) {\n                throw new InvalidUserDataException(message);\n            }\n        }\n\n        public void finishLastTest() {\n            if (current != null) {\n                current.close();\n                current = null;\n            }\n        }\n    }\n\n    private void assertEqualTestSnippetFromMigratedDocs() {\n        getTestRoot().getAsFileTree().matching(patternSet -> { patternSet.include(\"**/*asciidoc.yml\"); }).forEach(asciidocFile -> {\n            File mdxFile = new File(asciidocFile.getAbsolutePath().replace(\".asciidoc.yml\", \".mdx.yml\"));\n            if (mdxFile.exists() == false) {\n                throw new InvalidUserDataException(\"Couldn't find the corresponding mdx file for \" + asciidocFile.getAbsolutePath());\n            }\n            try {","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/doc/RestTestsFromDocSnippetTask.java#L485-L521","documentation":"checkUnconverted runs at the end of the build. It maintains two sets: expected unconverted candidates (configured via getExpectedUnconvertedCandidates()) and actually-found unconverted candidates (snippets flagged isConsoleCandidate). The 'listed but not found' list collects every expected file that had no unconverted snippet. If that list is non-empty (and the found-but-not-listed list is empty), the combined message starts with this line, meaning a file was declared as still-containing-unconverted-snippets but all its snippets have actually been converted to console.","triggerScenarios":"The expectedUnconvertedCandidates list property references a doc file path, but that file contains no console-candidate (unconverted) snippets — every snippet was already marked // CONSOLE or [source,console].","commonSituations":"An author finished converting a doc file's snippets to console but forgot to remove the file from the expectedUnconvertedCandidates allowlist in build.gradle; or the file path in the allowlist is stale after a rename/move.","solutions":["Remove the listed-but-not-found file path(s) (shown in the message) from the expectedUnconvertedCandidates configuration in build.gradle.","If a file was renamed, update the path in expectedUnconvertedCandidates to the new location or delete the stale entry."],"exampleFix":"// before — allowlist still references a fully-converted file\nrestTestsTask.getExpectedUnconvertedCandidates().set(List.of(\n    \"setting-up/security.asciidoc\",  // fully converted, no longer unconverted\n    \"ingest/pipelines.asciidoc\"\n))\n\n// after — remove the converted file\nrestTestsTask.getExpectedUnconvertedCandidates().set(List.of(\n    \"ingest/pipelines.asciidoc\"\n))","handlingStrategy":"validation","validationCode":"// Keep the expectedUnconvertedCandidates allowlist in sync with actual unconverted files\nimport java.nio.file.*;\nimport java.util.*;\nimport java.util.stream.*;\n\nvoid checkExpectedUnconverted(File docsDir, List<String> expected) throws java.io.IOException {\n    // expected = files that SHOULD still have unconverted snippets\n    // (this lint is the inverse: confirm each expected file actually has a CONSOLE candidate)\n    List<String> stale = new ArrayList<>();\n    for (String rel : expected) {\n        Path p = docsDir.toPath().resolve(rel);\n        if (!Files.exists(p) || !Files.readString(p).contains(\"// CONSOLE\")) {\n            stale.add(rel);\n        }\n    }\n    if (!stale.isEmpty()) {\n        throw new IllegalStateException(\n            \"These files are fully converted but still in expectedUnconvertedCandidates: \" + stale\n            + \". Remove them from the list.\");\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When you finish converting a doc file's snippets to console, immediately remove it from expectedUnconvertedCandidates.","After renaming or moving a doc file, update the allowlist path accordingly.","Treat the build error message's file list as the exact set of entries to remove from the allowlist."],"tags":["docs","unconverted","console","allowlist","gradle","migration"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}