{"record":{"id":"40d136ddd910c446","repo":"MuntashirAkon/AppManager","slug":"stream-has-already-been-finished","errorCode":null,"errorMessage":"Stream has already been finished","messagePattern":"Stream has already been finished","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"app/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java","lineNumber":335,"sourceCode":"     * output stream for writing the contents of the entry. Once this method is called, the stream\n     * is ready for calls to write() to write the entry's contents. Once the contents are written,\n     * closeArchiveEntry() <B>MUST</B> be called to ensure that all buffered data is completely\n     * written to the output stream.\n     *\n     * @param archiveEntry The TarEntry to be written to the archive.\n     * @throws IOException on error\n     * @throws ClassCastException if archiveEntry is not an instance of TarArchiveEntry\n     * @throws IllegalArgumentException if the {@link TarArchiveOutputStream#longFileMode} equals\n     *                                  {@link TarArchiveOutputStream#LONGFILE_ERROR} and the file\n     *                                  name is too long\n     * @throws IllegalArgumentException if the {@link TarArchiveOutputStream#bigNumberMode} equals\n     *         {@link TarArchiveOutputStream#BIGNUMBER_ERROR} and one of the numeric values\n     *         exceeds the limits of a traditional tar header.\n     */\n    @Override\n    public void putArchiveEntry(final ArchiveEntry archiveEntry) throws IOException {\n        if (finished) {\n            throw new IOException(\"Stream has already been finished\");\n        }\n        final TarArchiveEntry entry = (TarArchiveEntry) archiveEntry;\n        if (entry.isGlobalPaxHeader()) {\n            final byte[] data = encodeExtendedPaxHeadersContents(entry.getExtraPaxHeaders());\n            entry.setSize(data.length);\n            entry.writeEntryHeader(recordBuf, zipEncoding, bigNumberMode == BIGNUMBER_STAR);\n            writeRecord(recordBuf);\n            currSize= entry.getSize();\n            currBytes = 0;\n            this.haveUnclosedEntry = true;\n            write(data);\n            closeArchiveEntry();\n        } else {\n            final Map<String, String> paxHeaders = new HashMap<>();\n            final String entryName = entry.getName();\n            final boolean paxHeaderContainsPath = handleLongName(entry, entryName, paxHeaders, \"path\",\n                TarConstants.LF_GNUTYPE_LONGNAME, \"file name\");\n","sourceCodeStart":317,"sourceCodeEnd":353,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java#L317-L353","documentation":"putArchiveEntry checks the finished flag and throws IOException if the archive was already finished, since no new entries can be added after the end-of-archive records were written. finish() may have been called directly or via close().","triggerScenarios":"Calling putArchiveEntry after finish() or close(); reusing a finished TarArchiveOutputStream for another archive; a helper (handleLongName, writePaxHeaders, addManifestEntry) invoked on a finished stream.","commonSituations":"Writing archives in a loop where a later iteration uses a closed stream; returning the stream from a method after closing; accidentally closing in a finally block then continuing to write entries.","solutions":["Create a new TarArchiveOutputStream if you need to keep writing.","Reorder logic so all putArchiveEntry/closeArchiveEntry pairs happen before finish/close.","Guard entry-writing code paths with a check on your own 'archive open' state."],"exampleFix":"// before\ntar.close();\ntar.putArchiveEntry(entry); // throws\n// after\ntry (TarArchiveOutputStream tar2 = new TarArchiveOutputStream(out2)) {\n    tar2.putArchiveEntry(entry);\n    tar2.closeArchiveEntry();\n}","handlingStrategy":"try-catch","validationCode":"// Guard with your own lifecycle flag\nif (archiveClosed) throw new IllegalStateException(\"archive already closed\");","typeGuard":null,"tryCatchPattern":"try {\n    tar.putArchiveEntry(entry);\n} catch (IOException e) {\n    if (\"Stream has already been finished\".equals(e.getMessage())) {\n        // reopen a fresh stream or abort the batch\n    } else throw e;\n}","preventionTips":["Keep one owner of the stream lifecycle","Never reuse a closed TarArchiveOutputStream","Create a new stream for a new archive"],"tags":["tar","stream-state","use-after-close"],"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"}