MuntashirAkon/AppManager · error · IOException
premature end of tar archive. Didn't find any entry after…
Error message
premature end of tar archive. Didn't find any entry after PAX header.
What it means
Thrown by paxHeaders() when, after reading a per-file PAX extended header (typeflag 'x'), the next call to getNextEntry() returns null — meaning the archive ended without the real entry that the PAX header describes.
Solutions
- Verify the archive is complete (size/hash check) and re-download if not
- Only read archives after the producer has finished writing them
- Catch IOException around getNextTarEntry and report a truncated archive
- Re-create the archive with GNU tar/bsdtar if the source is known-bad
Example fix
// before
TarArchiveEntry e = tin.getNextTarEntry();
// after
try {
TarArchiveEntry e = tin.getNextTarEntry();
// process
} catch (IOException ex) {
throw new IOException("Truncated archive: entry missing after PAX header", ex);
} Defensive patterns
Strategy: try-catch
Try / catch
try {
while ((e = tin.getNextTarEntry()) != null) { process(e); }
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().contains("premature end")) {
throw new IOException("Archive truncated after PAX header", e);
}
throw e;
} Prevention
- Verify archive size/hash before extraction
- Read only after the producer closes the file
- Handle EOF markers (two zero blocks) correctly in custom writers
When it happens
Trigger: A PAX 'x' header block is followed by end-of-archive markers or EOF instead of the actual file entry — typically a truncated download or a tar cut short while being written.
Common situations: Interrupted downloads/uploads; streaming a tar that is still being produced; archives truncated by disk-full during copy.
Related errors
- Error detected parsing the pax header
- Failed to read Paxheader. Encountered a non-number while…
- Failed to read Paxheader. Expected
- Failed to read Paxheader.GNU.sparse.offset is expected…
- Failed to read Paxheader.Value should end with a newline
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/0c96b46e28a82283.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java:600
*
* For PAX Format 1.X:
* The sparse map itself is stored in the file data block, preceding the actual file data.
* It consists of a series of decimal numbers delimited by newlines. The map is padded with nulls to the nearest block boundary.
* The first number gives the number of entries in the map. Following are map entries, each one consisting of two numbers
* giving the offset and size of the data block it describes.
* @throws IOException
*/
private void paxHeaders() throws IOException {
List<TarArchiveStructSparse> sparseHeaders = new ArrayList<>();
final Map<String, String> headers = TarUtils.parsePaxHeaders(this, sparseHeaders, globalPaxHeaders, entrySize);
// for 0.1 PAX Headers
if (headers.containsKey("GNU.sparse.map")) {
sparseHeaders = TarUtils.parsePAX01SparseHeaders(headers.get("GNU.sparse.map"));
}
getNextEntry(); // Get the actual file entry
if (currEntry == null) {
throw new IOException("premature end of tar archive. Didn't find any entry after PAX header.");
}
applyPaxHeadersToCurrentEntry(headers, sparseHeaders);
// for 1.0 PAX Format, the sparse map is stored in the file data block
if (currEntry.isPaxGNU1XSparse()) {
sparseHeaders = TarUtils.parsePAX1XSparseHeaders(inputStream, recordSize);
currEntry.setSparseHeaders(sparseHeaders);
}
// sparse headers are all done reading, we need to build
// sparse input streams using these sparse headers
buildSparseInputStreams();
}
private void applyPaxHeadersToCurrentEntry(final Map<String, String> headers, final List<TarArchiveStructSparse> sparseHeaders) {
currEntry.updateEntryFromPaxHeaders(headers);
currEntry.setSparseHeaders(sparseHeaders);
}View on GitHub (pinned to 0152f468fc)