MuntashirAkon/AppManager · error · KeyStoreException
Stored pass is empty for alias
Error message
Stored pass is empty for alias ${alias} What it means
getAliasPassword checks whether an encrypted password exists for the given keystore alias via sSharedPreferences.contains(prefAlias). If the subsequent getString returns null despite contains() being true, it throws KeyStoreException "Stored pass is empty for alias ..." — the stored value is null or the pref entry is corrupt.
Solutions
- Remove the corrupt pref entry and re-save the alias password so it is stored as a String.
- Verify nothing writes the alias pref with a non-String type (contains() is true but getString returns null).
- Wrap the read in a null check that falls back to prompting the user for the password instead of failing.
Example fix
// before
String encryptedPass = sSharedPreferences.getString(prefAlias, null);
if (encryptedPass == null) {
throw new KeyStoreException("Stored pass is empty for alias " + alias);
}
// after
String encryptedPass = sSharedPreferences.getString(prefAlias, null);
if (encryptedPass == null) {
sSharedPreferences.edit().remove(prefAlias).apply(); // clear corrupt entry
encryptedPass = promptAndEncryptPassword(alias); // re-store as String
if (encryptedPass == null) throw new KeyStoreException("Stored pass is empty for alias " + alias);
} Defensive patterns
Strategy: validation
Validate before calling
// before calling getAliasPassword/getKey
String prefAlias = getPrefAlias(alias);
String stored = sSharedPreferences.getString(prefAlias, null);
if (stored == null || stored.isEmpty()) {
// prompt user for the alias password and save it first
saveAliasPassword(alias, promptForPassword(alias));
} Try / catch
// try
try {
char[] pass = keyStoreManager.getKey(alias);
} catch (KeyStoreException e) {
if (e.getMessage().contains("Stored pass is empty")) {
// corrupt/typed pref entry: clear and re-store
removeAliasPasswordPref(alias);
promptAndStoreAliasPassword(alias);
}
} Prevention
- Only store alias passwords as String entries via the app's own encrypt-and-save API.
- Check getString(...) directly rather than trusting contains() when reading prefs.
- Serialize pref writes on a single thread to avoid partial reads/writes.
- Never hand-edit or post-process the app's SharedPreferences XML.
When it happens
Trigger: Calling getAliasPassword(alias) (directly or via getKey) when sSharedPreferences.contains(getPrefAlias(alias)) is true but getString(prefAlias, null) returns null.
Common situations: Prefs XML manually edited or partially written; type mismatch after pref written with a different type (e.g. as a Set) so getString returns null; concurrent write/clear during read.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- Alias exists.
- Alias app_manager does not exist in KeyStore.
- Checksums for master key did not match.
- Could not decrypt encrypted password.
- Could not load AES local protection key from keystore
AI-assisted analysis of MuntashirAkon/AppManager@0152f468fc (2026-09-12).
Data as JSON: /api/errors/1fdbd1cd558f486f.
Report an issue: GitHub.
Appendix: source
Thrown at app/src/main/java/io/github/muntashirakon/AppManager/crypto/ks/KeyStoreManager.java:499
throw new KeyStoreException("Could not decrypt encrypted password.");
}
return realPassword;
}
/**
* @return Password for the given alias. {@link Utils#clearChars(char[])} must be called when done.
* @deprecated Kept for migratory purposes only, deprecated since v2.6.3. To be removed in v3.0.0.
*/
@Deprecated
@CheckResult
@NonNull
private char[] getAliasPassword(@NonNull String alias) throws KeyStoreException {
char[] password;
String prefAlias = getPrefAlias(alias);
if (sSharedPreferences.contains(prefAlias)) {
String encryptedPass = sSharedPreferences.getString(prefAlias, null);
if (encryptedPass == null) {
throw new KeyStoreException("Stored pass is empty for alias " + alias);
}
password = getDecryptedPassword(mContext, encryptedPass);
if (password == null) {
throw new KeyStoreException("Decrypted pass is empty for alias " + alias);
}
return password;
} else {
IntentFilter filter = new IntentFilter(ACTION_KS_INTERACTION_BEGIN);
filter.addAction(ACTION_KS_INTERACTION_END);
ContextCompat.registerReceiver(mContext, mReceiver, filter, ContextCompat.RECEIVER_NOT_EXPORTED);
Intent broadcastIntent = new Intent(ACTION_KS_INTERACTION_BEGIN);
broadcastIntent.setPackage(mContext.getPackageName());
mContext.sendBroadcast(broadcastIntent);
// Intent wrapper
Intent intent = new Intent(mContext, KeyStoreActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(KeyStoreActivity.EXTRA_ALIAS, alias);
String ks = "AM KeyStore";View on GitHub (pinned to 0152f468fc)