MuntashirAkon/AppManager · error · org.xmlpull.v1.XmlPullParserException

Invalid tag: ${tagName}

Error message

Invalid tag: ${tagName}

What it means

XmlPullParserException thrown by SharedPrefsUtil.readSharedPref when the XML parser encounters an element tag that is not one of the recognized shared-preference tags (string, set, etc.) while reading a preferences file. The utility expects a well-formed Android SharedPreferences XML export; any unknown element makes the structure ambiguous, so parsing is aborted rather than silently skipping data.

Source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/sharedpref/SharedPrefsUtil.java:93

                    case TAG_SET:
                        Set<String> stringSet = new HashSet<>();
                        prefs.put(attrName, stringSet);
                        // Grab all strings
                        event = parser.next();
                        tagName = parser.getName();
                        while (event != XmlPullParser.END_TAG || !Objects.equals(tagName, TAG_SET)) {
                            if (event == XmlPullParser.START_TAG) {
                                if (!Objects.equals(tagName, TAG_STRING)) {
                                    throw new XmlPullParserException("Invalid tag inside <set>: " + tagName);
                                }
                                stringSet.add(parser.nextText());
                            }
                            event = parser.next();
                            tagName = parser.getName();
                        }
                        break;
                    default:
                        throw new XmlPullParserException("Invalid tag: " + tagName);
                }
            }
            event = parser.next();
        }
        return prefs;
    }

    public static void writeSharedPref(@NonNull OutputStream os, @NonNull Map<String, Object> hashMap)
            throws IOException {
        XmlSerializer xmlSerializer = Xml.newSerializer();
        StringWriter stringWriter = new StringWriter();
        xmlSerializer.setOutput(stringWriter);
        xmlSerializer.startDocument("UTF-8", true);
        xmlSerializer.startTag("", TAG_ROOT);
        // Add values
        for (String name : hashMap.keySet()) {
            Object value = hashMap.get(name);
            if (value instanceof Boolean) {

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Add handling for the unsupported tag types (int, long, boolean, float) in the parser's switch statement before the default branch
  2. Inspect the file being parsed and remove/convert the unrecognized element to a supported type (e.g. stringify ints/booleans)
  3. Regenerate the XML using App Manager's own export so only supported tags are present
  4. Wrap the readSharedPref call in a try-catch for XmlPullParserException and fall back to a partial/default prefs map

Example fix

// before
default:
    throw new XmlPullParserException("Invalid tag: " + tagName);
// after
case "int":
    prefs.put(tagName, String.valueOf(Integer.parseInt(parser.nextText())));
    break;
case "boolean":
    prefs.put(tagName, parser.nextText());
    break;
default:
    throw new XmlPullParserException("Invalid tag: " + tagName);
Defensive patterns

Strategy: validation

Validate before calling

Set<String> allowed = Set.of("string", "string-set", "set", rootTag);
boolean parseable = doc.getRootElement().getChildNodes().stream()
    .allMatch(n -> allowed.contains(n.getNodeName()));
if (!parseable) throw new IllegalArgumentException("Unsupported pref tag in XML");

Type guard

boolean isSupportedTag(String tag) {
    return "string".equals(tag) || "set".equals(tag) || "string-set".equals(tag);
}

Try / catch

try {
    prefs = SharedPrefsUtil.readSharedPref(xmlFile);
} catch (XmlPullParserException e) {
    Log.w(TAG, "Unrecognized pref tag: " + e.getMessage(), e);
    prefs = Collections.emptyMap();
}

Prevention

When it happens

Trigger: Calling readSharedPref on an XML file whose <map> body contains an element type not handled by the parser's switch statement (e.g. <int>, <long>, <boolean>, <float> from a standard Android prefs export, or arbitrary/renamed tags from a hand-edited or third-party generated file); tagName is read from parser.getName() at each iteration and falls through to the default branch.

Common situations: Restoring preferences exported from a different tool or Android version that wrote numeric/boolean pref types which this util does not support; hand-editing the XML and introducing a typo in a tag name; concatenating XML from multiple sources.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12). Data as JSON: /api/errors/c821af258a818453. Report an issue: GitHub.