shwenzhang/AndResGuard · error · IOException

Failed to obtain key with alias

Error message

Failed to obtain key with alias "<keyAlias>" from <keystoreFile>. Wrong password?

What it means

This IOException is thrown when KeyStore.getKey(alias, password) raises UnrecoverableKeyException while loading the signer's private key from the keystore. It means the keystore itself was opened, but the key under the given alias could not be decrypted/recovered with the supplied key password. The library appends 'Wrong password?' because that is by far the most common cause.

Solutions

  1. Verify the key password with keytool: 'keytool -list -v -keystore <keystoreFile>' and re-enter the password used when generating the key entry.
  2. If the key password differs from the keystore password, pass it explicitly via --ks-key-pass instead of relying on --ks-pass.
  3. Re-import the key into a fresh keystore with a known key password if the original password is lost.
  4. Confirm the alias is correct; a wrong alias pointing at a key with a different password can also trigger UnrecoverableKeyException.

Example fix

// before
sign({ ks: 'release.jks', ksPass: 'storepass', ksKeyAlias: 'release' })
// after
sign({ ks: 'release.jks', ksPass: 'storepass', ksKeyPass: 'keypass', ksKeyAlias: 'release' })
Defensive patterns

Strategy: try-catch

Validate before calling

// Before signing, verify key recovery
KeyStore ks = KeyStore.getInstance(new File(ksFile), ksPassword.toCharArray());
Key key = ks.getKey(alias, keyPassword != null ? keyPassword.toCharArray() : ksPassword.toCharArray());
if (key == null) throw new IllegalArgumentException("Alias not found: " + alias);

Type guard

boolean isRecoverableKey(KeyStore ks, String alias, char[] pass) {
  try { return ks.getKey(alias, pass) instanceof PrivateKey; }
  catch (UnrecoverableKeyException e) { return false; }
}

Try / catch

try {
  signerParams.loadPrivateKeyAndCerts(passwordRetriever);
} catch (IOException e) {
  if (e.getMessage() != null && e.getMessage().contains("Wrong password?")) {
    // prompt user / re-fetch key password from secret manager and retry once
  } else throw e;
}

Prevention

When it happens

Trigger: Running apksigner-style signing (loadPrivateKeyAndCerts -> loadPrivateKeyAndCertsFromKeyStore) where --ks-key-alias names an existing alias but the provided key password does not match the one used when the key entry was created, or no key password is supplied for a keystore whose key entries use a different password than the keystore password.

Common situations: CI pipelines that set only the keystore password but the key entry was created with a distinct key password; keystores migrated between formats (JKS<->PKCS12) where key entry passwords were lost; copy-pasting the alias from a different keystore; typos or stale secrets rotated in the keystore but not in build config.

Related errors


AI-assisted analysis of shwenzhang/AndResGuard@e4df245d82 (2026-09-12). Data as JSON: /api/errors/ee5b6eff383e9289. Report an issue: GitHub.

Appendix: source

Thrown at AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java:760

                "Key \"" + keyAlias + "\" password for " + name
            );
            entryKey = getKeyStoreKey(ks, keyAlias, keyPasswords);
          }
        }

        if (entryKey == null) {
          throw new ParameterException(keystoreFile + " entry \"" + keyAlias + "\" does not contain a key");
        } else if (!(entryKey instanceof PrivateKey)) {
          throw new ParameterException(keystoreFile
                                       + " entry \""
                                       + keyAlias
                                       + "\" does not contain a private"
                                       + " key. It contains a key of algorithm: "
                                       + entryKey.getAlgorithm());
        }
        key = (PrivateKey) entryKey;
      } catch (UnrecoverableKeyException e) {
        throw new IOException("Failed to obtain key with alias \""
                              + keyAlias
                              + "\" from "
                              + keystoreFile
                              + ". Wrong password?", e);
      }
      this.privateKey = key;
      Certificate[] certChain = ks.getCertificateChain(keyAlias);
      if ((certChain == null) || (certChain.length == 0)) {
        throw new ParameterException(keystoreFile + " entry \"" + keyAlias + "\" does not contain certificates");
      }
      this.certs = new ArrayList<>(certChain.length);
      for (Certificate cert : certChain) {
        this.certs.add((X509Certificate) cert);
      }
    }

    private void loadPrivateKeyAndCertsFromFiles(PasswordRetriever passwordRetriver) throws Exception {
      if (keyFile == null) {

View on GitHub (pinned to e4df245d82)