skylot/jadx · error · RuntimeException
Failed to parse xml
Error message
Failed to parse xml
What it means
Thrown by JadxSecurity.parseXml when the underlying DocumentBuilder.parse(in) call fails for any reason (SAXException, IOException, IllegalArgumentException, etc.). Jadx wraps all exceptions in a generic RuntimeException because parseXml is called from multiple code paths (AndroidManifest.xml, resource XML, etc.) that do not declare checked exceptions. The secure vs. simple factory is selected by the SECURE_XML_PARSER flag but both paths share the same catch.
Source
Thrown at jadx-core/src/main/java/jadx/api/security/impl/JadxSecurity.java:113
Matcher matcher = SANITIZE_GRADLE_PATTERN.matcher(str);
if (matcher.find()) {
return matcher.replaceAll("");
}
return str;
}
@Override
public Document parseXml(InputStream in) {
DocumentBuilderFactory dbf;
if (flags.contains(JadxSecurityFlag.SECURE_XML_PARSER)) {
dbf = SecureDBFHolder.INSTANCE;
} else {
dbf = SimpleDBFHolder.INSTANCE;
}
try {
return dbf.newDocumentBuilder().parse(in);
} catch (Exception e) {
throw new RuntimeException("Failed to parse xml", e);
}
}
private static final class SimpleDBFHolder {
private static final DocumentBuilderFactory INSTANCE = DocumentBuilderFactory.newInstance();
}
private static final class SecureDBFHolder {
private static final DocumentBuilderFactory INSTANCE = buildSecureDBF();
private static DocumentBuilderFactory buildSecureDBF() {
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://apache.org/xml/features/dom/create-entity-ref-nodes", false);View on GitHub (pinned to e738a26571)
Solutions
- Inspect getCause() — a SAXException indicates malformed XML content; an IOException indicates stream reading failure.
- Validate the input is well-formed text XML before calling parseXml, especially if the source may be binary AXML (convert it first with the AXML decoder).
- If the SECURE_XML_PARSER flag is set and DTD/external entities are legitimately needed (rare), disable that flag — but be aware of XXE risks.
- Catch the RuntimeException around parseXml and log the offending resource name so processing of the rest of the APK can continue.
Example fix
// before
Document doc = jadxSecurity.parseXml(inputStream);
// after: validate and handle
Document doc;
try {
doc = jadxSecurity.parseXml(inputStream);
} catch (RuntimeException e) {
LOG.warn("Failed to parse XML resource", e.getCause());
doc = null; // or skip resource
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate that the stream contains text XML, not binary AXML
byte[] first = new byte[5];
inputStream.mark(5);
int read = inputStream.read(first);
inputStream.reset();
if (read >= 1 && first[0] == 0x03) { // binary AXML magic number
throw new IllegalArgumentException("Input is binary AXML, not text XML — convert first");
} Try / catch
Document doc;
try {
doc = jadxSecurity.parseXml(inputStream);
} catch (RuntimeException e) {
Throwable cause = e.getCause();
if (cause instanceof org.xml.sax.SAXException) {
LOG.warn("Malformed XML: {}", cause.getMessage());
} else if (cause instanceof java.io.IOException) {
LOG.warn("IO error reading XML: {}", cause.getMessage());
}
doc = null;
} Prevention
- Validate that input is text XML, not binary AXML, before calling parseXml — check for the 0x03 magic byte.
- Catch RuntimeException (not checked exceptions) around parseXml since it wraps all failures.
- Log the cause (not the wrapper) to distinguish SAX parse errors from IO errors.
When it happens
Trigger: Calling parseXml(in) with a stream containing malformed XML, non-XML binary data, truncated content, or an unsupported encoding declaration. Also triggered if the InputStream throws IOException during reading, or if the input is null (though a null stream typically yields a different NullPointerException before the catch). The secure parser may additionally reject XML with DTD or external entity references.
Common situations: Decompiling an APK whose AndroidManifest.xml or resources.arsc XML is corrupted or obfuscated. Binary XML (AXML format) fed to parseXml instead of text XML. A truncated or partially downloaded APK where the XML resource is incomplete. Custom jadx integrations that pass unvalidated streams to parseXml.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Failed to save JSON file: {}
- Failed to save JSON file: {}
- Failed to init common directories
- Failed to create temp root directory
- {}
AI-assisted analysis of skylot/jadx@e738a26571 (2026-08-14).
Data as JSON: /api/errors/28290651ad04892c.
Report an issue: GitHub.