{"record":{"id":"900e616ca1c8dc9e","repo":"MuntashirAkon/AppManager","slug":"password-for-alias-could-not-be-saved","errorCode":null,"errorMessage":"Password for ${alias} could not be saved.","messagePattern":"Password for (.+?) could not be saved\\.","errorType":"exception","errorClass":"KeyStoreException","httpStatus":null,"severity":"critical","filePath":"app/src/main/java/io/github/muntashirakon/AppManager/crypto/ks/KeyStoreManager.java","lineNumber":272,"sourceCode":"    }\n\n    public void addKeyPair(String alias, @NonNull KeyPair keyPair, boolean isOverride)\n            throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {\n        // Check existence of this alias in system preferences, this should be unique\n        String prefAlias = getPrefAlias(alias);\n        if (sSharedPreferences.contains(prefAlias) && mAmKeyStore.containsAlias(alias)) {\n            Log.w(TAG, \"Alias %s exists.\", alias);\n            if (isOverride) removeItemInternal(alias);\n            else return;\n        }\n        char[] password = getAmKeyStorePassword();\n        PrivateKey privateKey = keyPair.getPrivateKey();\n        Certificate certificate = keyPair.getCertificate();\n        mAmKeyStore.setKeyEntry(alias, privateKey, password, new Certificate[]{certificate});\n        String encryptedPass = getEncryptedPassword(mContext, password);\n        if (encryptedPass == null) {\n            mAmKeyStore.deleteEntry(alias);\n            throw new KeyStoreException(\"Password for \" + alias + \" could not be saved.\");\n        }\n        sSharedPreferences.edit().putString(prefAlias, encryptedPass).apply();\n        try (OutputStream is = new FileOutputStream(AM_KEYSTORE_FILE)) {\n            mAmKeyStore.store(is, password);\n            Utils.clearChars(password);\n            Utils.clearChars(password);\n        }\n    }\n\n    public void addSecretKey(String alias, @NonNull SecretKey secretKey, boolean isOverride)\n            throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {\n        // Check existence of this alias in system preferences, this should be unique\n        String prefAlias = getPrefAlias(alias);\n        if (sSharedPreferences.contains(prefAlias) && mAmKeyStore.containsAlias(alias)) {\n            if (!isOverride) throw new KeyStoreException(\"Alias \" + alias + \" exists.\");\n            else Log.w(TAG, \"Alias %s exists.\", alias);\n        }\n        char[] password = getAmKeyStorePassword();","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/MuntashirAkon/AppManager/blob/0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5/app/src/main/java/io/github/muntashirakon/AppManager/crypto/ks/KeyStoreManager.java#L254-L290","documentation":"addKeyPair stores a KeyPair in the AM keystore and then encrypts its keystore password for persistence. If getEncryptedPassword returns null (encryption of the password failed), the just-added entry is rolled back (deleteEntry) and a KeyStoreException is thrown, leaving the keystore unchanged.","triggerScenarios":"getEncryptedPassword(mContext, password) returns null because the AES local-protection key used for password encryption is unavailable or encryption fails while adding a key pair (also reached from AdbConnectionManager and migrateKeyStore).","commonSituations":"Keystore corruption so the protection key cannot be used; device-credential reset invalidating keys; migration from an old keystore on a broken keystore state.","solutions":["Fix the underlying crypto failure: verify the AES local-protection key loads (see getAesGcmLocalProtectionKey) before retrying","Retry addKeyPair after keystore access is restored","Clear/reset keystore state and re-add keys, accepting loss of previously protected data"],"exampleFix":"// before\nString encryptedPass = getEncryptedPassword(mContext, password);\nif (encryptedPass == null) {\n    mAmKeyStore.deleteEntry(alias);\n    throw new KeyStoreException(\"Password for \" + alias + \" could not be saved.\");\n}\n// after\nString encryptedPass = getEncryptedPassword(mContext, password);\nif (encryptedPass == null) {\n    mAmKeyStore.deleteEntry(alias);\n    throw new KeyStoreException(\"Password for \" + alias + \" could not be saved.\",\n            new KeyStoreException(\"Password encryption unavailable; check local protection key\"));\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    ksManager.addKeyPair(alias, keyPair, password, false);\n} catch (KeyStoreException e) {\n    // password encryption failed; keystore state rolled back\n    showKeystoreUnavailableError();\n}","preventionTips":["Confirm the AES local-protection key loads before keystore writes","Handle device-credential resets that invalidate keystore keys","Treat keystore write failures as atomic: alias is rolled back on password-save failure"],"tags":["keystore","crypto","android"],"backgroundTag":"keystore-key-unavailable","analyzedSha":"0152f468fc9463ee02dc2ca83f6fe4989a2c4ca5","analyzedAt":"2026-09-12T14:03:37.243Z","contentChangedAt":"2026-09-12T14:03:37.243Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}