MuntashirAkon/AppManager · critical · java.lang.IllegalStateException

Failed parsing settings file: ${statePersistFile}

Error message

Failed parsing settings file: ${statePersistFile}

What it means

IllegalStateException thrown when neither the primary settings XML file nor the fallback copy could be parsed: parseStateFromXmlStreamLocked returned false for the fallback stream too. This means the on-disk settings state is unreadable/corrupt in both locations, and loading it is refused to avoid treating corrupt data as valid settings.

Source

Thrown at app/src/main/java/io/github/muntashirakon/AppManager/ssaid/SettingsStateV26.java:859

        Path statePersistFallbackFile = Paths.get(mStatePersistFile.getFilePath() + FALLBACK_FILE_SUFFIX);
        Log.i(LOG_TAG, "Failed parsing settings file: %s, retrying with fallback file: %s", mStatePersistFile,
                statePersistFallbackFile);
        try {
            in = new AtomicExtendedFile(statePersistFallbackFile.getFile()).openRead();
        } catch (IOException | RemoteException fnfe) {
            final String message = "No fallback file found for: " + mStatePersistFile;
            throw new IllegalStateException(message, fnfe);
        }
        if (parseStateFromXmlStreamLocked(in)) {
            // Parsed state from fallback file. Restore original file with fallback file
            try {
                IoUtils.copy(statePersistFallbackFile, mStatePersistFile);
            } catch (IOException ignored) {
                // Failed to copy, but it's okay because we already parsed states from fallback file
            }
        } else {
            final String message = "Failed parsing settings file: " + mStatePersistFile;
            throw new IllegalStateException(message);
        }
    }

    @GuardedBy("mLock")
    private boolean parseStateFromXmlStreamLocked(InputStream in) {
        try {
            TypedXmlPullParser parser = Xml.resolvePullParser(in);
            parseStateLocked(parser);
            return true;
        } catch (XmlPullParserException | IOException e) {
            return false;
        } finally {
            IoUtils.closeQuietly(in);
        }
    }

    /**
     * Uses AtomicExtendedFile to check if the file or its backup exists.

View on GitHub (pinned to 0152f468fc)

Solutions

  1. Replace both settings_ssaid.xml copies with a known-good backup
  2. Delete the corrupt files and let the settings state be re-initialized from defaults
  3. Validate the XML well-formedness manually (adb pull + xmllint) to confirm the corruption before deciding
  4. Catch IllegalStateException at the init call site and fall back to an empty/default SsaidSettings instance

Example fix

// before
mSettingsState = init(ssaidLocation, userId); // throws on corrupt XML
// after
try {
    mSettingsState = init(ssaidLocation, userId);
} catch (IllegalStateException e) {
    Log.w(TAG, "Corrupt settings_ssaid.xml, using defaults", e);
    mSettingsState = SsaidSettings.empty(userId);
}
Defensive patterns

Strategy: fallback

Validate before calling

// validate XML before loading
try (InputStream in = new FileInputStream(file)) {
    new XmlPullParser().setInput(new InputStreamReader(in));
    // advance through document; XmlPullParserException => corrupt
} catch (Exception e) {
    Log.w(TAG, "settings file corrupt, will need rebuild");
}

Try / catch

try {
    state = SsaidSettings.load(userId);
} catch (IllegalStateException e) {
    Log.e(TAG, "Both settings files corrupt; rebuilding from defaults", e);
    state = SsaidSettings.empty(userId);
}

Prevention

When it happens

Trigger: Fallback file opens successfully but its XML content fails structural validation in parseStateFromXmlStreamLocked (truncated write, garbage bytes, wrong root element, mid-write crash), so the else branch after the copy attempt throws with the primary file's name in the message.

Common situations: Power loss or process kill during an atomic write leaving both files damaged; manual editing saving malformed XML; an incompatible version of the file format produced by another tool.

Understand the failure class

Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.

Related errors


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