{"record":{"id":"8c6c3391609a4f4a","repo":"iBotPeaches/Apktool","slug":"parser-must-be-on-text-or-end-tag-to-read-text","errorCode":null,"errorMessage":"Parser must be on TEXT or END_TAG to read text.","messagePattern":"Parser must be on TEXT or END_TAG to read text\\.","errorType":"exception","errorClass":"XmlPullParserException","httpStatus":null,"severity":"error","filePath":"brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/BinaryXmlResourceParser.java","lineNumber":556,"sourceCode":"    @Override\n    public void require(int type, String namespace, String name) throws XmlPullParserException {\n        if (type != mEventType || (namespace != null && !namespace.equals(getNamespace()))\n                || (name != null && !name.equals(getName()))) {\n            throw new XmlPullParserException(TYPES[type] + \" is expected.\", this, null);\n        }\n    }\n\n    @Override\n    public String nextText() throws XmlPullParserException, IOException {\n        if (mEventType != START_TAG) {\n            throw new XmlPullParserException(\"Parser must be on START_TAG to read next text.\", this, null);\n        }\n        int eventType = next();\n        if (eventType == END_TAG) {\n            return \"\";\n        }\n        if (eventType != TEXT) {\n            throw new XmlPullParserException(\"Parser must be on TEXT or END_TAG to read text.\", this, null);\n        }\n        String result = getText();\n        eventType = next();\n        if (eventType != END_TAG) {\n            throw new XmlPullParserException(\"Event TEXT must be immediately followed by END_TAG.\", this, null);\n        }\n        return result;\n    }\n\n    @Override\n    public int nextTag() throws XmlPullParserException, IOException {\n        int eventType = next();\n        if (eventType == TEXT && isWhitespace()) {\n            eventType = next();\n        }\n        if (eventType != START_TAG && eventType != END_TAG) {\n            throw new XmlPullParserException(\"Expected start or end tag.\", this, null);\n        }","sourceCodeStart":538,"sourceCodeEnd":574,"githubUrl":"https://github.com/iBotPeaches/Apktool/blob/79b63384d7d7e22917e6ea8b453272da7012515b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/decoder/BinaryXmlResourceParser.java#L538-L574","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nString value = parser.nextText(); // throws on nested tags\n\n// after (mixed-content-safe)\nStringBuilder sb = new StringBuilder();\nint depth = 1;\nwhile (depth > 0) {\n    int ev = parser.next();\n    if (ev == XmlPullParser.TEXT) sb.append(parser.getText());\n    else if (ev == XmlPullParser.START_TAG) depth++;\n    else if (ev == XmlPullParser.END_TAG) depth--;\n}\nString value = sb.toString();","handlingStrategy":"validation","validationCode":"int ev = parser.next();\nif (ev == XmlPullParser.END_TAG) { /* empty element: text = \"\" */ }\nelse if (ev != XmlPullParser.TEXT) { /* mixed content: iterate events manually */ }","typeGuard":null,"tryCatchPattern":"try {\n    String text = parser.nextText();\n} catch (XmlPullParserException e) {\n    if (e.getMessage().contains(\"TEXT or END_TAG\")) {\n        // element has nested tags — fall back to manual event iteration\n    }\n}","preventionTips":["Use event loops for elements that can contain child tags.","Don't assume AXML elements are always text-only."],"tags":["apktool","xml-pull-parser","mixed-content","axml"],"backgroundTag":null,"analyzedSha":"79b63384d7d7e22917e6ea8b453272da7012515b","analyzedAt":"2026-08-14T10:43:28.812Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}