{"record":{"id":"b0876ddb152e796a","repo":"MuntashirAkon/AppManager","slug":"this-archive-contains-unclosed-entries","errorCode":null,"errorMessage":"This archive contains unclosed entries.","messagePattern":"This archive contains unclosed entries\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java","lineNumber":276,"sourceCode":"    }\n\n    /**\n     * Ends the TAR archive without closing the underlying OutputStream.\n     *\n     * An archive consists of a series of file entries terminated by an\n     * end-of-archive entry, which consists of two 512 blocks of zero bytes.\n     * POSIX.1 requires two EOF records, like some other implementations.\n     *\n     * @throws IOException on error\n     */\n    @Override\n    public void finish() throws IOException {\n        if (finished) {\n            throw new IOException(\"This archive has already been finished\");\n        }\n\n        if (haveUnclosedEntry) {\n            throw new IOException(\"This archive contains unclosed entries.\");\n        }\n        writeEOFRecord();\n        writeEOFRecord();\n        padAsNeeded();\n        out.flush();\n        finished = true;\n    }\n\n    /**\n     * Closes the underlying OutputStream.\n     *\n     * @throws IOException on error\n     */\n    @Override\n    public void close() throws IOException {\n        try {\n            if (!finished) {\n                finish();","sourceCodeStart":258,"sourceCodeEnd":294,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java#L258-L294","documentation":"finish() refuses to finalize the archive while an entry is still open (putArchiveEntry was called without a matching closeArchiveEntry), because writing the end-of-archive records would produce a truncated, invalid tar. The caller must close the current entry first.","triggerScenarios":"Calling finish() or close() after putArchiveEntry(entry) without calling closeArchiveEntry(); an exception in entry-writing code skipping closeArchiveEntry().","commonSituations":"Early returns/exceptions in the middle of writing an entry; forgetting closeArchiveEntry after copying entry data; conditional code paths that skip entry close.","solutions":["Call closeArchiveEntry() for every putArchiveEntry() before finishing.","Use try/finally (or try-with-resources on the entry-writing logic) to guarantee closeArchiveEntry runs.","Write exactly currSize bytes so closeArchiveEntry itself succeeds before finish."],"exampleFix":"// before\ntar.putArchiveEntry(entry);\ntar.write(data);\ntar.finish(); // throws: unclosed entry\n// after\ntar.putArchiveEntry(entry);\ntry { tar.write(data); } finally { tar.closeArchiveEntry(); }\ntar.finish();","handlingStrategy":"try-catch","validationCode":"// Ensure all entries are closed before finishing\nif (openEntryCount > 0) { throw new IllegalStateException(\"close all entries before finish()\"); }","typeGuard":null,"tryCatchPattern":"try {\n    tar.finish();\n} catch (IOException e) {\n    if (e.getMessage().contains(\"unclosed entries\")) {\n        tar.closeArchiveEntry(); tar.finish();\n    } else throw e;\n}","preventionTips":["Pair every putArchiveEntry with closeArchiveEntry in try/finally","Write exactly entry.getSize() bytes","Centralize entry-writing in one utility method"],"tags":["tar","stream-state","unclosed-entry","resource-leak"],"backgroundTag":"invalid-state-transition","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}