MuntashirAkon/AppManager · error · org.xmlpull.v1.XmlPullParserException
Unknown entity
Error message
Unknown entity ${entity} What it means
resolveEntity() maps the small set of predefined XML entities (amp, lt, gt, apos, quot) plus numeric character references (#123;) to characters. Any other entity name in a binary XML TEXT node has no defined meaning, so an XmlPullParserException "Unknown entity <entity>" is thrown.
Solutions
- Replace named HTML entities with the actual characters or numeric character references (  for ) in the source document before binary encoding.
- Pre-process text content to resolve entities with a text XML parser before writing binary XML.
- If you control the writer, escape only the five predefined XML entities.
Example fix
// before // binary XML contains: "hello world" -> Unknown entity nbsp // after // source text: "hello\u00A0world" or "hello world"
Defensive patterns
Strategy: validation
Validate before calling
static boolean isSupportedEntity(String name) {
return name.equals("amp") || name.equals("lt") || name.equals("gt")
|| name.equals("apos") || name.equals("quot")
|| (name.length() > 1 && name.charAt(0) == '#');
} Try / catch
try {
parser.setInput(is, null);
// parse text nodes
} catch (XmlPullParserException e) {
if (e.getMessage().startsWith("Unknown entity")) {
// sanitize source text and re-encode the document
}
} Prevention
- Use only the five predefined XML entities or numeric character references in source text.
- Resolve HTML named entities ( , ©) before binary encoding.
- Sanitize text content at the writing stage so entities never reach the binary format.
When it happens
Trigger: consumeToken() reads a TEXT token whose resolved entity name is not one of the five predefined XML entities and does not start with '#' as a numeric character reference — i.e. named entities like or custom entities embedded in the binary stream.
Common situations: Documents converted from text XML that contained HTML-style named entities ( , ©) before binary encoding; tooling that wrote entities verbatim without escaping/resolving them; hand-crafted binary XML containing unsupported entity names.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/8dcf0070acdd5680.
Report an issue: GitHub.
Appendix: source
Thrown at libcore/compat/src/main/java/io/github/muntashirakon/compat/xml/BinaryXmlPullParser.java:342
return;
}
}
}
static @NonNull String resolveEntity(@NonNull String entity)
throws XmlPullParserException {
switch (entity) {
case "lt": return "<";
case "gt": return ">";
case "amp": return "&";
case "apos": return "'";
case "quot": return "\"";
}
if (entity.length() > 1 && entity.charAt(0) == '#') {
final char c = (char) Integer.parseInt(entity.substring(1));
return new String(new char[] { c });
}
throw new XmlPullParserException("Unknown entity " + entity);
}
@Override
public void require(int type, String namespace, String name)
throws XmlPullParserException, IOException {
if (namespace != null && !namespace.isEmpty()) throw illegalNamespace();
if (mCurrentToken != type || !Objects.equals(mCurrentName, name)) {
throw new XmlPullParserException(getPositionDescription());
}
}
@Override
public String nextText() throws XmlPullParserException, IOException {
if (getEventType() != START_TAG) {
throw new XmlPullParserException(getPositionDescription());
}
int eventType = next();
if (eventType == TEXT) {View on GitHub (pinned to 0152f468fc)