MuntashirAkon/AppManager · error · IOException
This archive has already been finished
Error message
This archive has already been finished
What it means
TarArchiveOutputStream.finish() writes the end-of-archive records; calling it more than once is invalid, so the second call throws IOException because the internal 'finished' flag is already set. close() calls finish(), so manual finish() followed by close() triggers this.
Solutions
- Call finish() only once, or rely on close() which finishes automatically.
- Track whether you already finished and skip the second call.
- If using try-with-resources, remove the explicit finish() call.
Example fix
// before tar.finish(); tar.close(); // finish() runs again -> throws // after tar.close(); // close() finishes the archive exactly once
Defensive patterns
Strategy: try-catch
Validate before calling
// Track finish state yourself
boolean archiveFinished = false;
if (!archiveFinished) { tar.finish(); archiveFinished = true; } Try / catch
try {
tar.finish();
} catch (IOException e) {
if (!"This archive has already been finished".equals(e.getMessage())) throw e;
// already finished: safe to ignore
} Prevention
- Prefer close() alone — it finishes exactly once
- Use try-with-resources
- Do not call finish() and close() both in helper chains
When it happens
Trigger: Calling finish() then close(); calling finish() twice; wrapping the stream in code that both finishes and closes (e.g. try-with-resources after an explicit finish()).
Common situations: Manual resource management without try-with-resources; helper methods that finish the archive while a caller also closes it; retry logic that re-invokes finish after a partial failure.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- No current entry to close
- No current tar entry
- No current tar entry
- Stream has already been finished
- This archive contains unclosed entries.
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/df27c8fff8e7725f.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java:272
@Override
public long getBytesWritten() {
return countingOut.getBytesWritten();
}
/**
* Ends the TAR archive without closing the underlying OutputStream.
*
* An archive consists of a series of file entries terminated by an
* end-of-archive entry, which consists of two 512 blocks of zero bytes.
* POSIX.1 requires two EOF records, like some other implementations.
*
* @throws IOException on error
*/
@Override
public void finish() throws IOException {
if (finished) {
throw new IOException("This archive has already been finished");
}
if (haveUnclosedEntry) {
throw new IOException("This archive contains unclosed entries.");
}
writeEOFRecord();
writeEOFRecord();
padAsNeeded();
out.flush();
finished = true;
}
/**
* Closes the underlying OutputStream.
*
* @throws IOException on error
*/
@OverrideView on GitHub (pinned to 0152f468fc)