MuntashirAkon/AppManager · error · IOException

e.getMessage()

Error message

e.getMessage()

What it means

Xml.isBinaryXml() peeks the first 4 bytes of the stream to detect Android binary XML (AXML). When the stream is a FileInputStream it reads via Os.pread on the underlying file descriptor, and an ErrnoException from the kernel (bad fd, I/O error, permission) is rethrown as an IOException carrying the errno message. It signals that the file could not be read at the OS level, not that the XML is malformed.

Source

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

    static {
        boolean useAbx;
        try {
            useAbx = (boolean) Objects.requireNonNull(Class.forName("android.os.SystemProperties")
                    .getDeclaredMethod("getBoolean", String.class, boolean.class)
                    .invoke(null, "persist.sys.binary_xml", Build.VERSION.SDK_INT >= Build.VERSION_CODES.S));
        } catch (Exception ignore) {
            useAbx = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
        }
        ENABLE_BINARY_DEFAULT = useAbx;
    }

    public static boolean isBinaryXml(@NonNull InputStream in) throws IOException {
        final byte[] magic = new byte[4];
        if (in instanceof FileInputStream) {
            try {
                Os.pread(((FileInputStream) in).getFD(), magic, 0, magic.length, 0);
            } catch (ErrnoException e) {
                throw new IOException(e.getMessage(), e);
            }
        } else {
            if (!in.markSupported()) {
                in = new BufferedInputStream(in);
            }
            in.mark(8);
            in.read(magic);
            in.reset();
        }
        return Arrays.equals(magic, BinaryXmlSerializer.PROTOCOL_MAGIC_VERSION_0);
    }

    public static boolean isBinaryXml(@NonNull ByteBuffer buffer) {
        final byte[] magic = new byte[4];
        buffer.mark();
        buffer.get(magic);
        buffer.reset();
        return Arrays.equals(magic, BinaryXmlSerializer.PROTOCOL_MAGIC_VERSION_0);

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Verify the file exists and is readable before opening: File.canRead() and length() >= 0.
  2. Ensure the FileInputStream is opened by the caller and not closed or reused after a previous parse; open a fresh stream per parse.
  3. If pread keeps failing, wrap the stream yourself in a BufferedInputStream so isBinaryXml takes the mark/reset path instead of the FD path.
  4. Catch IOException around resolvePullParser and surface the file path plus the errno message to diagnose the storage-level problem.

Example fix

// before
InputStream in = new FileInputStream(f);
XmlResourceParser p = Xml.resolvePullParser(in); // may throw IOException: pread errno
// after
File f = new File(path);
if (!f.canRead()) throw new IOException("Cannot read " + path);
InputStream in = new BufferedInputStream(new FileInputStream(f)); // avoids FD pread path
XmlResourceParser p = Xml.resolvePullParser(in);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!file.canRead() || file.length() < 4) throw new IOException("File missing or too small: " + file);

Try / catch

try {
    XmlResourceParser p = Xml.resolvePullParser(in);
} catch (IOException e) {
    throw new IOException("Cannot read XML source: " + e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling Xml.resolvePullParser() (which calls isBinaryXml) on a FileInputStream whose descriptor cannot be pread: closed FD, file deleted between open and read, EIO on a damaged filesystem, or a special file (pipe/device) that doesn't support positional reads.

Common situations: Parsing an APK entry extracted to a temp file that was deleted before parsing; opening a path obtained from another process whose FD was closed; storage corruption on SD card or /proc-style pseudo-files passed in directly.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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