{"record":{"id":"da539fdd28824b88","repo":"elastic/elasticsearch","slug":"failed-to-tail-log","errorCode":null,"errorMessage":"Failed to tail log {}","messagePattern":"Failed to tail log (.+?)","errorType":"exception","errorClass":"UncheckedIOException","httpStatus":null,"severity":"warning","filePath":"build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java","lineNumber":1156,"sourceCode":"                                Pair.of(\n                                    ring.getLast(), // Original, non-normalized message (so we keep the first timestamp)\n                                    ofNullable(errorsAndWarnings.get(normalizedMessage)).map(p -> p.right() + 1).orElse(1)\n                                )\n                            );\n                        }\n                    } else {\n                        // We combine multi line log messages to make sure we never break exceptions apart\n                        lineToAdd = ring.removeLast() + \"\\n\" + line;\n                    }\n                }\n                ring.add(lineToAdd);\n                if (ring.size() >= TAIL_LOG_MESSAGES_COUNT) {\n                    ring.removeFirst();\n                }\n            }\n        } catch (IOException e) {\n            if (tailLogs) {\n                throw new UncheckedIOException(\"Failed to tail log \" + this, e);\n            }\n            return;\n        }\n\n        boolean foundLeaks = false;\n        for (String logLine : errorsAndWarnings.keySet()) {\n            if (logLine.contains(\"ResourceLeakDetector\") || logLine.contains(\"LeakTracker\")) {\n                tailLogs = true;\n                foundLeaks = true;\n                break;\n            }\n        }\n        if (tailLogs) {\n            if (errorsAndWarnings.isEmpty() == false || ring.isEmpty() == false) {\n                LOGGER.lifecycle(\"\\n=== {} `{}` ===\", description, this);\n            }\n            if (errorsAndWarnings.isEmpty() == false) {\n                LOGGER.lifecycle(\"\\n»    ↓ errors and warnings from \" + from + \" ↓\");","sourceCodeStart":1138,"sourceCodeEnd":1174,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/build-tools/src/main/java/org/elasticsearch/gradle/testclusters/ElasticsearchNode.java#L1138-L1174","documentation":"Thrown while reading the ES output log file (esOutputFile) in logFileContents after the cluster stops, when an IOException escapes the LineNumberReader and tailLogs is true. tailLogs is true when the caller explicitly requested the full log (e.g. on failure) or when leak-detector lines were detected. The plugin fails loudly here because losing the diagnostic log on a failing run would hide the real error.","triggerScenarios":"Files.newBufferedReader(from) or reader.readLine() throws — the log file was deleted, moved, or its permissions changed between cluster start and the post-stop log sweep. On Windows the file may still be locked by the just-killed JVM.","commonSituations":"A concurrent cleanup task (reaper, gradle clean) deleted the working dir while the log was being tailed; the working dir is on a tmpfs that got cleared; antivirus quarantined the log; or a previous run's file handle is still open on Windows.","solutions":["Check that no parallel gradle task or external process is deleting the testclusters working directory during the run.","If on Windows, ensure antivirus exclusions for the gradle build dir; file locking by AV is a common cause.","Run the test in isolation (--tests <one>) to rule out concurrency between clusters sharing a working dir root.","If the file was legitimately gone, re-run: this is often transient and the log will be present next time."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if (Files.exists(from) == false) {\n    LOGGER.warn(\"Log file {} gone before tail; skipping\", from);\n    return;\n}","typeGuard":null,"tryCatchPattern":"try (LineNumberReader reader = new LineNumberReader(Files.newBufferedReader(from))) {\n    ...\n} catch (IOException e) {\n    if (tailLogs) throw new UncheckedIOException(\"Failed to tail log \" + this, e);\n    return;\n}","preventionTips":["Do not delete the testclusters working dir while a build is running.","On Windows, exclude the gradle build dir from antivirus on-access scanning.","Run flaky tests in isolation to rule out concurrency on shared working dirs."],"tags":["testclusters","log-tail","io","windows"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T08:17:17.861Z"}