MuntashirAkon/AppManager · error · IOException

e

Error message

e

What it means

resolvePullParser() attaches the input stream to a fast XmlPullParser and calls setInput(in, "UTF-8"), which parses the initial document prolog immediately. If the stream does not contain well-formed XML text, the parser throws XmlPullParserException, which is translated to an IOException so callers only need to handle IOException. This means the data was not parseable XML text at all (as opposed to Android binary XML, which is detected beforehand by isBinaryXml).

Source

Thrown at libcore/compat/src/main/java/io/github/muntashirakon/compat/xml/Xml.java:117

     * <p>
     * To ensure that both formats are detected and transparently handled
     * correctly, you must shift to using both {@link #resolveSerializer} and
     * {@code #resolvePullParser}.
     */
    public static @NonNull TypedXmlPullParser resolvePullParser(@NonNull InputStream in) throws IOException {
        if (!in.markSupported()) {
            in = new BufferedInputStream(in);
        }
        final TypedXmlPullParser xml;
        if (isBinaryXml(in)) {
            xml = newBinaryPullParser();
        } else {
            xml = newFastPullParser();
        }
        try {
            xml.setInput(in, StandardCharsets.UTF_8.name());
        } catch (XmlPullParserException e) {
            throw new IOException(e);
        }
        return xml;
    }

    /**
     * Creates a new {@link XmlSerializer} which is optimized for use inside the
     * system, typically by supporting only a basic set of features.
     * <p>
     * In particular, the returned parser does not support namespaces, prefixes,
     * properties, or options.
     */
    @SuppressWarnings("AndroidFrameworkEfficientXml")
    public static @NonNull TypedXmlSerializer newFastSerializer() {
        return XmlUtils.makeTyped(new FastXmlSerializer());
    }

    /**
     * Creates a new {@link XmlSerializer} that writes XML documents using a

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Dump the first bytes of the stream and confirm they start with an XML prolog ('<?xml' or '<') before parsing.
  2. Check for Android binary XML first (0x03 0x00 0x08 0x00 magic) via Xml.isBinaryXml and use an AXML-capable parser if it matches.
  3. Verify you extracted the correct file entry and that it is complete (compare sizes/hashes with the source archive).
  4. Catch IOException around resolvePullParser and log the first 64 bytes of input to identify what was actually passed in.

Example fix

// before
XmlResourceParser p = Xml.resolvePullParser(stream);
// after
stream.mark(8);
byte[] head = new byte[4];
int n = stream.read(head);
stream.reset();
if (n == 4 && head[0] == 0x03 && head[1] == 0x00) {
    throw new IOException("Binary XML (AXML) detected; use a binary XML parser");
}
XmlResourceParser p = Xml.resolvePullParser(stream);
Defensive patterns

Strategy: try-catch

Validate before calling

in.mark(8); byte[] h = new byte[4]; int n = in.read(h); in.reset();
if (n < 4) throw new IOException("Input too short to be XML");
if (h[0] == 0x03 && h[1] == 0x00) throw new IOException("Binary AXML, not text XML");
if (h[0] != '<' && !(h[0] == (byte)0xEF)) throw new IOException("Input does not look like XML text");

Try / catch

try {
    XmlResourceParser p = Xml.resolvePullParser(in);
} catch (IOException e) {
    // input was not well-formed XML text
    log.warn("XML parse failed: " + e.getMessage());
}

Prevention

When it happens

Trigger: Passing a non-XML stream to Xml.resolvePullParser(): a raw binary file that is not AXML (e.g. PNG, DEX), a truncated XML document cut off before the root tag, or text with an invalid encoding/byte-order mark that fails UTF-8 prolog parsing.

Common situations: Extracting an APK entry with the wrong path and getting a different resource file; downloading a manifest over a broken connection and receiving an HTML error page; unzipping with an incorrect offset producing garbage bytes.

Related errors


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