MuntashirAkon/AppManager · error · IOException

"manifest" tag not found.

Error message

"manifest" tag not found.

What it means

ManifestParser.parseComponents throws IOException("\"manifest\" tag not found.") after decoding a binary Android XML (AXML) block when the document's root element is not named "manifest". A valid binary AndroidManifest.xml must have <manifest> as its root. If the root tag differs, the file is not an Android manifest, so parsing aborts.

Source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/apk/parser/ManifestParser.java:67

    private String mPackageName;

    public ManifestParser(@NonNull byte[] manifestBytes) {
        this(ByteBuffer.wrap(manifestBytes));
    }

    public ManifestParser(@NonNull ByteBuffer manifestBytes) {
        mManifestBytes = manifestBytes;
    }

    public List<ManifestComponent> parseComponents() throws IOException {
        try (BlockReader reader = new BlockReader(mManifestBytes.array())) {
            ResXmlDocument xmlBlock = new ResXmlDocument();
            xmlBlock.readBytes(reader);
            xmlBlock.setPackageBlock(AndroidBinXmlDecoder.getFrameworkPackageBlock());
            ResXmlElement resManifestElement = xmlBlock.getDocumentElement();
            // manifest
            if (!TAG_MANIFEST.equals(resManifestElement.getName())) {
                throw new IOException("\"manifest\" tag not found.");
            }
            String packageName = getAttributeValue(resManifestElement, ATTR_MANIFEST_PACKAGE);
            if (packageName == null) {
                throw new IOException("\"manifest\" does not have required attribute \"package\".");
            }
            mPackageName = packageName;
            // manifest -> application
            ResXmlElement resApplicationElement = null;
            Iterator<ResXmlElement> resXmlElementIt = resManifestElement.getElements(TAG_APPLICATION);
            if (resXmlElementIt.hasNext()) {
                resApplicationElement = resXmlElementIt.next();
            }
            if (resXmlElementIt.hasNext()) {
                throw new IOException("\"manifest\" has duplicate \"application\" tags.");
            }
            if (resApplicationElement == null) {
                Log.i(TAG, "package %s does not have \"application\" tag.", mPackageName);
                return Collections.emptyList();

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Ensure the input is the APK's binary AndroidManifest.xml (extract with the correct entry name from the APK).
  2. Verify the file is compiled AXML, not plain-text XML; use the text parser for uncompiled manifests.
  3. Check the APK isn't corrupted or repackaged; re-obtain or rebuild it and inspect with aapt dump xmltree.
  4. Catch the IOException and report the file as an invalid APK rather than retrying parse.

Example fix

// before
parser.parseComponents(reader); // may throw "manifest" tag not found
// after
try (InputStream in = apk.getEntry("AndroidManifest.xml")) {
    byte[] axml = IOUtils.readFully(in);
    if (!(axml.length > 4 && axml[0] == 0x03 && axml[1] == 0)) {
        throw new IOException("Not a binary Android manifest (AXML).");
    }
    parser.parseComponents(new Buffer(new ByteBufferBackedInputStream(ByteBuffer.wrap(axml))));
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure it is binary AXML: first 2 bytes are 0x0003 (RES_XML_TYPE)
byte[] head = new byte[2];
try (InputStream in = apk.getEntry("AndroidManifest.xml")) {
    if (in.read(head) != 2) return false;
    return (head[0] & 0xFF) == 0x03 && (head[1] & 0xFF) == 0x00;
}

Type guard

static boolean isBinaryAxml(byte[] data) {
    return data != null && data.length >= 4 && (data[0] & 0xFF) == 0x03 && (data[1] & 0xFF) == 0x00;
}

Try / catch

try (var reader = manifestReader) {
    ManifestParser parser = new ManifestParser(reader);
    parser.parse();
} catch (IOException e) {
    if (e.getMessage().contains("manifest\" tag not found")) {
        report("Not a valid binary AndroidManifest.xml");
    } else throw e;
}

Prevention

When it happens

Trigger: parseComponents (via manifestComponents) is given a reader whose decoded ResXmlDocument has a root element other than "manifest" — e.g. the wrong XML file was passed (AndroidManifest of a library processed oddly, a layout, or a non-AXML file misinterpreted).

Common situations: Passing a plain-text (non-binary) manifest to a binary AXML parser, pointing the parser at the wrong entry in an APK, or a repackaged/corrupted APK whose manifest root was altered by an obfuscator or repack tool.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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