{"record":{"id":"c3bede7fd6c2c438","repo":"elastic/elasticsearch","slug":"compilationunit-has-no-lexical-information-for-out","errorCode":null,"errorMessage":"CompilationUnit has no lexical information for output","messagePattern":"CompilationUnit has no lexical information for output","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/AbstractVersionsTask.java","lineNumber":159,"sourceCode":"    static OptionalInt findSingleIntegerExpr(FieldDeclaration field) {\n        var ints = field.findAll(IntegerLiteralExpr.class);\n        switch (ints.size()) {\n            case 0 -> {\n                return OptionalInt.empty();\n            }\n            case 1 -> {\n                return OptionalInt.of(ints.get(0).asNumber().intValue());\n            }\n            default -> {\n                LOGGER.warn(\"Multiple integers found in version field declaration [{}]\", field); // and ignore it\n                return OptionalInt.empty();\n            }\n        }\n    }\n\n    static void writeOutNewContents(Path file, CompilationUnit unit) throws IOException {\n        if (unit.containsData(LexicalPreservingPrinter.NODE_TEXT_DATA) == false) {\n            throw new IllegalArgumentException(\"CompilationUnit has no lexical information for output\");\n        }\n        Files.writeString(file, LexicalPreservingPrinter.print(unit), StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);\n    }\n}\n","sourceCodeStart":141,"sourceCodeEnd":164,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/AbstractVersionsTask.java#L141-L164","documentation":"Thrown by AbstractVersionsTask.writeOutNewContents when the JavaParser CompilationUnit does not carry the LexicalPreservingPrinter.NODE_TEXT_DATA, meaning LexicalPreservingPrinter.setup() was never called on the parsed source. Without lexical info, LexicalPreservingPrinter.print cannot reproduce the original formatting, so the task refuses to write to avoid corrupting the source file.","triggerScenarios":"A CompilationUnit is parsed (StaticJavaParser.parse) and modified, then passed to writeOutNewContents. The guard checks unit.containsData(LexicalPreservingPrinter.NODE_TEXT_DATA); if the caller forgot to call LexicalPreservingPrinter.setup(unit) immediately after parsing (before observing/altering the tree), the data key is absent and the throw fires.","commonSituations":"Adding a new code path that transforms a parsed Java file but omits the LexicalPreservingPrinter.setup call; refactoring an existing release-version-rewriting routine and dropping the setup line; using a fresh CompilationUnit built programmatically rather than parsed+setup for round-trip printing.","solutions":["Ensure LexicalPreservingPrinter.setup(unit) is invoked right after parsing the source file and before any modification.","Do not construct a CompilationUnit via 'new CompilationUnit()' for output that must preserve formatting — parse the real file and call setup.","Re-run the release/version-rewrite task to confirm round-trip output is formatted correctly."],"exampleFix":"// before\nCompilationUnit unit = StaticJavaParser.parse(file);\n// ... mutate unit ...\nwriteOutNewContents(file, unit); // throws: no lexical info\n// after\nCompilationUnit unit = StaticJavaParser.parse(file);\nLexicalPreservingPrinter.setup(unit);\n// ... mutate unit ...\nwriteOutNewContents(file, unit);","handlingStrategy":"validation","validationCode":"CompilationUnit unit = StaticJavaParser.parse(file);\nLexicalPreservingPrinter.setup(unit); // MUST precede any mutation\nif (unit.containsData(LexicalPreservingPrinter.NODE_TEXT_DATA) == false) {\n    throw new IllegalStateException(\"LexicalPreservingPrinter not set up for \" + file);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always call LexicalPreservingPrinter.setup(unit) immediately after parsing when round-trip printing is intended.","Never use 'new CompilationUnit()' for files that must preserve original formatting.","Add a helper that parses+setups to make the pairing impossible to forget."],"tags":["build","gradle","release","javaparser","code-generation"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}