MuntashirAkon/AppManager · error · IOException

Entry ' ' closed at ' ' before the ' ' bytes specified in…

Error message

Entry '${currName}' closed at '${currBytes}' before the '${currSize}' bytes specified in the header were written

What it means

closeArchiveEntry verifies that the number of bytes written for the current entry equals the size declared in the tar header (setSize). If fewer bytes were written (currBytes < currSize), the archive would contain an entry whose data does not match its header, so the library throws with details of the shortfall.

Solutions

  1. Set entry size from the actual data: entry.setSize(data.length) or file.length(), and write exactly that many bytes.
  2. Copy the whole source stream and verify byte counts before closing.
  3. If the source may be truncated, read it fully into memory or adjust the size before putArchiveEntry (size is fixed once the header is written).

Example fix

// before
entry.setSize(1024); // guessed
tar.putArchiveEntry(entry);
tar.write(data); // data.length == 900
// after
entry.setSize(data.length);
tar.putArchiveEntry(entry);
tar.write(data);
tar.closeArchiveEntry();
Defensive patterns

Strategy: validation

Validate before calling

long actual = data.length; // or Files.size(path)
if (actual != entry.getSize()) entry.setSize(actual);

Try / catch

try {
    tar.closeArchiveEntry();
} catch (IOException e) {
    if (e.getMessage().contains("before the '")) {
        // entry under-written: mark archive invalid, rewrite with correct size
    } else throw e;
}

Prevention

When it happens

Trigger: Closing an entry after writing fewer bytes than TarArchiveEntry.getSize(); passing a smaller InputStream to copy than the declared size; setting an inflated size manually before writing.

Common situations: Hard-coded entry sizes out of sync with actual file content; interrupted file reads; computing size with one encoding/unit and writing with another; copying from a truncated source stream.

Understand the failure class

Background: payload too large / request exceeds maximum size: why libraries cap bytes and how to fix oversize payloads — this error's family across 50 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/5f77fbc87b659173. Report an issue: GitHub.

Appendix: source

Thrown at app/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveOutputStream.java:414

    /**
     * Close an entry. This method MUST be called for all file entries that contain data. The reason
     * is that we must buffer data written to the stream in order to satisfy the buffer's record
     * based writes. Thus, there may be data fragments still being assembled that must be written to
     * the output stream before this entry is closed and the next entry written.
     *
     * @throws IOException on error
     */
    @Override
    public void closeArchiveEntry() throws IOException {
        if (finished) {
            throw new IOException("Stream has already been finished");
        }
        if (!haveUnclosedEntry) {
            throw new IOException("No current entry to close");
        }
        out.flushBlock();
        if (currBytes < currSize) {
            throw new IOException("Entry '" + currName + "' closed at '"
                + currBytes
                + "' before the '" + currSize
                + "' bytes specified in the header were written");
        }
        recordsWritten += (int) (currSize / RECORD_SIZE);
        if (0 != currSize % RECORD_SIZE) {
            recordsWritten++;
        }
        haveUnclosedEntry = false;
    }

    /**
     * Writes bytes to the current tar archive entry. This method is aware of the current entry and
     * will throw an exception if you attempt to write bytes past the length specified for the
     * current entry.
     *
     * @param wBuf The buffer to write to the archive.
     * @param wOffset The offset in the buffer from which to get bytes.

View on GitHub (pinned to 0152f468fc)