{"record":{"id":"e12433a4ebf5a20a","repo":"MuntashirAkon/AppManager","slug":"failed-parsing-settings-file-statepersistfile","errorCode":null,"errorMessage":"Failed parsing settings file: ${statePersistFile}","messagePattern":"Failed parsing settings file: (.+?)","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"critical","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/ssaid/SettingsStateV26.java","lineNumber":859,"sourceCode":"        Path statePersistFallbackFile = Paths.get(mStatePersistFile.getFilePath() + FALLBACK_FILE_SUFFIX);\n        Log.i(LOG_TAG, \"Failed parsing settings file: %s, retrying with fallback file: %s\", mStatePersistFile,\n                statePersistFallbackFile);\n        try {\n            in = new AtomicExtendedFile(statePersistFallbackFile.getFile()).openRead();\n        } catch (IOException | RemoteException fnfe) {\n            final String message = \"No fallback file found for: \" + mStatePersistFile;\n            throw new IllegalStateException(message, fnfe);\n        }\n        if (parseStateFromXmlStreamLocked(in)) {\n            // Parsed state from fallback file. Restore original file with fallback file\n            try {\n                IoUtils.copy(statePersistFallbackFile, mStatePersistFile);\n            } catch (IOException ignored) {\n                // Failed to copy, but it's okay because we already parsed states from fallback file\n            }\n        } else {\n            final String message = \"Failed parsing settings file: \" + mStatePersistFile;\n            throw new IllegalStateException(message);\n        }\n    }\n\n    @GuardedBy(\"mLock\")\n    private boolean parseStateFromXmlStreamLocked(InputStream in) {\n        try {\n            TypedXmlPullParser parser = Xml.resolvePullParser(in);\n            parseStateLocked(parser);\n            return true;\n        } catch (XmlPullParserException | IOException e) {\n            return false;\n        } finally {\n            IoUtils.closeQuietly(in);\n        }\n    }\n\n    /**\n     * Uses AtomicExtendedFile to check if the file or its backup exists.","sourceCodeStart":841,"sourceCodeEnd":877,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/ssaid/SettingsStateV26.java#L841-L877","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Replace both settings_ssaid.xml copies with a known-good backup","Delete the corrupt files and let the settings state be re-initialized from defaults","Validate the XML well-formedness manually (adb pull + xmllint) to confirm the corruption before deciding","Catch IllegalStateException at the init call site and fall back to an empty/default SsaidSettings instance"],"exampleFix":"// before\nmSettingsState = init(ssaidLocation, userId); // throws on corrupt XML\n// after\ntry {\n    mSettingsState = init(ssaidLocation, userId);\n} catch (IllegalStateException e) {\n    Log.w(TAG, \"Corrupt settings_ssaid.xml, using defaults\", e);\n    mSettingsState = SsaidSettings.empty(userId);\n}","handlingStrategy":"fallback","validationCode":"// validate XML before loading\ntry (InputStream in = new FileInputStream(file)) {\n    new XmlPullParser().setInput(new InputStreamReader(in));\n    // advance through document; XmlPullParserException => corrupt\n} catch (Exception e) {\n    Log.w(TAG, \"settings file corrupt, will need rebuild\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    state = SsaidSettings.load(userId);\n} catch (IllegalStateException e) {\n    Log.e(TAG, \"Both settings files corrupt; rebuilding from defaults\", e);\n    state = SsaidSettings.empty(userId);\n}","preventionTips":["Keep a known-good backup of settings_ssaid.xml","Avoid killing the process mid-write; use atomic file APIs","Validate saved XML after every write in tests","Treat parse failure as data loss and rebuild deterministically"],"tags":["android","file-io","corruption","parsing","ssaid"],"backgroundTag":"file-read-failed","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}