iBotPeaches/Apktool · error · XmlPullParserException
Parser must be on TEXT or END_TAG to read text.
Error message
Parser must be on TEXT or END_TAG to read text.
What it means
Inside nextText(): after consuming the START_TAG, the next event must be TEXT or END_TAG (an empty element yields END_TAG and returns ""). Any other event type — START_TAG (nested element where text was expected) or END_DOCUMENT — throws this.
Source
Thrown at brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/BinaryXmlResourceParser.java:556
@Override
public void require(int type, String namespace, String name) throws XmlPullParserException {
if (type != mEventType || (namespace != null && !namespace.equals(getNamespace()))
|| (name != null && !name.equals(getName()))) {
throw new XmlPullParserException(TYPES[type] + " is expected.", this, null);
}
}
@Override
public String nextText() throws XmlPullParserException, IOException {
if (mEventType != START_TAG) {
throw new XmlPullParserException("Parser must be on START_TAG to read next text.", this, null);
}
int eventType = next();
if (eventType == END_TAG) {
return "";
}
if (eventType != TEXT) {
throw new XmlPullParserException("Parser must be on TEXT or END_TAG to read text.", this, null);
}
String result = getText();
eventType = next();
if (eventType != END_TAG) {
throw new XmlPullParserException("Event TEXT must be immediately followed by END_TAG.", this, null);
}
return result;
}
@Override
public int nextTag() throws XmlPullParserException, IOException {
int eventType = next();
if (eventType == TEXT && isWhitespace()) {
eventType = next();
}
if (eventType != START_TAG && eventType != END_TAG) {
throw new XmlPullParserException("Expected start or end tag.", this, null);
}View on GitHub (pinned to 79b63384d7)
Solutions
- Handle mixed content: iterate next() events inside the element and only treat TEXT events as text instead of calling nextText().
- If the element is genuinely text-only by spec, the input AXML is malformed — inspect it with `apktool d` or a hex dump.
- Guard with `if (parser.next() == XmlPullParser.TEXT)` patterns instead of assuming nextText() semantics.
- Verify the APK with aapt2 to rule out corruption.
Example fix
// before
String value = parser.nextText(); // throws on nested tags
// after (mixed-content-safe)
StringBuilder sb = new StringBuilder();
int depth = 1;
while (depth > 0) {
int ev = parser.next();
if (ev == XmlPullParser.TEXT) sb.append(parser.getText());
else if (ev == XmlPullParser.START_TAG) depth++;
else if (ev == XmlPullParser.END_TAG) depth--;
}
String value = sb.toString(); Defensive patterns
Strategy: validation
Validate before calling
int ev = parser.next();
if (ev == XmlPullParser.END_TAG) { /* empty element: text = "" */ }
else if (ev != XmlPullParser.TEXT) { /* mixed content: iterate events manually */ } Try / catch
try {
String text = parser.nextText();
} catch (XmlPullParserException e) {
if (e.getMessage().contains("TEXT or END_TAG")) {
// element has nested tags — fall back to manual event iteration
}
} Prevention
- Use event loops for elements that can contain child tags.
- Don't assume AXML elements are always text-only.
When it happens
Trigger: Calling nextText() on an element that contains a child element instead of text (e.g. `<string><b>hi</b></string>` style AXML), or a malformed binary XML whose events skip straight to END_DOCUMENT.
Common situations: Parsing app widgets/manifests where an element assumed to be text-only actually nests tags; AXML files whose event sequence was corrupted by packers; lenient hand-written XML fed through a compiler that kept nesting.
Related errors
- Event TEXT must be immediately followed by END_TAG.
- Could not initialize parser.
- Parser must be on START_TAG to read next text.
- Expected start or end tag.
- Attribute index out of range: index=%s, length=%s
AI-assisted analysis of iBotPeaches/Apktool@79b63384d7 (2026-08-14).
Data as JSON: /api/errors/8c6c3391609a4f4a.
Report an issue: GitHub.