MuntashirAkon/AppManager · error · IOException
Truncated TAR archive
Error message
Truncated TAR archive
What it means
Thrown by getActuallySkipped when the underlying stream could not skip as many bytes as requested while reading an entry or its padding. Because skipping fewer bytes than expected desynchronizes the parser, the stream reports the archive as truncated.
Solutions
- Verify the archive's size against the source (re-download; compare byte counts/hashes)
- Use streams that report correct available/skip semantics (avoid wrapping in streams that short-circuit skip)
- Wait until writing of the tar is complete before reading
- Catch IOException, and consider implementing a manual read-loop skip for streams with unreliable skip
Example fix
// before
long n = in.skip(entrySize); // may skip fewer bytes silently elsewhere
// after
long remaining = entrySize;
byte[] buf = new byte[8192];
while (remaining > 0) {
long r = in.read(buf, 0, (int) Math.min(buf.length, remaining));
if (r < 0) throw new IOException("Truncated TAR archive");
remaining -= r;
} Defensive patterns
Strategy: try-catch
Validate before calling
if (archiveFile.length() < expectedMinimumSize) {
throw new IOException("archive incomplete");
} Try / catch
try {
// iterate entries, read data
} catch (IOException e) {
if (e.getMessage().contains("Truncated TAR archive")) {
throw new IOException("Archive incomplete — re-download required", e);
}
throw e;
} Prevention
- Verify file size/hash after download before extraction
- Only read completed archives
- Prefer explicit read-loops over skip() for untrusted streams
When it happens
Trigger: skip(long) or skipRecordPadding() reaches EOF before the full entry data/padding has been consumed — the archive file is shorter than its headers claim.
Common situations: Partially downloaded or interrupted transfers; archives copied with truncation (disk-full during copy); reading a still-being-written tar.
Related errors
- APK files backup is requested but no APK files have been…
- Backup failed for
- Backup failed for
- broken archive, entry with negative size
- Could not backup KeyStore item.
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/549eedf5ad445f99.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/org/apache/commons/compress/archivers/tar/TarArchiveInputStream.java:465
/**
* For FileInputStream, the skip always return the number you input, so we
* need the available bytes to determine how many bytes are actually skipped
*
* @param available available bytes returned by inputStream.available()
* @param skipped skipped bytes returned by inputStream.skip()
* @param expected bytes expected to skip
* @return number of bytes actually skipped
* @throws IOException if a truncated tar archive is detected
*/
private long getActuallySkipped(final long available, final long skipped, final long expected) throws IOException {
long actuallySkipped = skipped;
if (inputStream instanceof FileInputStream) {
actuallySkipped = Math.min(skipped, available);
}
if (actuallySkipped != expected) {
throw new IOException("Truncated TAR archive");
}
return actuallySkipped;
}
/**
* Get the next entry in this tar archive as longname data.
*
* @return The next entry in the archive as longname data, or null.
* @throws IOException on error
*/
protected byte[] getLongNameData() throws IOException {
// read in the name
final ByteArrayOutputStream longName = new ByteArrayOutputStream();
int length = 0;
while ((length = read(smallBuf)) >= 0) {
longName.write(smallBuf, 0, length);
}View on GitHub (pinned to 0152f468fc)