MuntashirAkon/AppManager · error · IOException

Wrong header version: " + s

Error message

Wrong header version: " + s

What it means

IOException from AndroidBackupHeader.read when the header version line parsed from the .ab stream is not the supported value (1). The Android backup format version is checked immediately after the magic; any other version is rejected.

Solutions

  1. Verify the file starts with 'ANDROID BACKUP\n1\n' and is a genuine .ab backup
  2. Use a converter for newer backup versions before this extractor
  3. Re-transfer/re-create the backup if the header is corrupted
  4. Ensure you're not passing a TAR file directly where an .ab is expected

Example fix

// before
InputStream is = new FileInputStream("backup.tar"); // wrong format
new AndroidBackupHeader(is, pwd).toTar();
// after
InputStream is = new FileInputStream("backup.ab");
String head = readFirstLine(is);
if (!"ANDROID BACKUP".equals(head)) throw new IOException("Not an Android backup");
new AndroidBackupHeader(is, pwd).toTar();
Defensive patterns

Strategy: validation

Validate before calling

// Check the version line before handing the stream to the header parser
List<String> lines = readHeaderLines(abFile, 2);
if (!"ANDROID BACKUP".equals(lines.get(0))) throw new IOException("Not an Android backup");
if (!"1".equals(lines.get(1))) throw new IOException("Unsupported backup version: " + lines.get(1));

Try / catch

try {
    InputStream tar = header.toTar();
} catch (IOException e) {
    if (e.getMessage().startsWith("Wrong header version")) {
        Log.e(TAG, "Backup format version not supported; convert first", e);
    } else throw e;
}

Prevention

When it happens

Trigger: The second header line (after 'ANDROID BACKUP') is not "1" — e.g. archives from newer tooling with version 2/5, corrupted first lines, or the stream is not actually an Android backup at all.

Common situations: Feeding a plain TAR or a compressed file to the extractor; backups produced by alternative implementations using a different version; truncated/mangled transfers shifting header lines.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/backup/adb/AndroidBackupHeader.java:96

            String s = readHeaderLine(backupStream);
            mBackupFileVersion = Integer.parseInt(s);
            if (mBackupFileVersion <= BACKUP_FILE_VERSION) {
                // okay, it's a version we recognize.  if it's version 1, we may need
                // to try two different PBKDF2 regimes to compare checksums.
                final boolean pbkdf2Fallback = (mBackupFileVersion == 1);

                s = readHeaderLine(backupStream);
                mCompress = (Integer.parseInt(s) != 0);
                s = readHeaderLine(backupStream);
                if (s.equals("none")) {
                    // no more header to parse; we're good to go
                } else if (mPassword != null && mPassword.length > 0) { // AES-256
                    preCompressStream = decodeAesHeaderAndInitialize(mPassword, s, pbkdf2Fallback, backupStream);
                } else {
                    throw new IOException("Archive is encrypted but no password given");
                }
            } else {
                throw new IOException("Wrong header version: " + s);
            }
        } else {
            throw new IOException("Didn't read the right header magic");
        }

        // okay, use the right stream layer based on compression
        return mCompress ? new InflaterInputStream(preCompressStream) : preCompressStream;
    }

    @NonNull
    public OutputStream write(@NonNull OutputStream backupStream) throws Exception {
        // Write the global file header.  All strings are UTF-8 encoded; lines end
        // with a '\n' byte.  Actual backup data begins immediately following the
        // final '\n'.
        //
        // line 1: "ANDROID BACKUP"
        // line 2: backup file format version, currently "5"
        // line 3: compressed?  "0" if not compressed, "1" if compressed.

View on GitHub (pinned to 0152f468fc)