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

  1. Replace named HTML entities with the actual characters or numeric character references (&#160; for &nbsp;) in the source document before binary encoding.
  2. Pre-process text content to resolve entities with a text XML parser before writing binary XML.
  3. If you control the writer, escape only the five predefined XML entities.

Example fix

// before
// binary XML contains: "hello&nbsp;world" -> Unknown entity nbsp
// after
// source text: "hello\u00A0world" or "hello&#160;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

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 &nbsp; or custom entities embedded in the binary stream.

Common situations: Documents converted from text XML that contained HTML-style named entities (&nbsp;, &copy;) 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)