shwenzhang/AndResGuard · error · ParameterException

entry " " does not contain certificates

Error message

<keystoreFile> entry "<keyAlias>" does not contain certificates

What it means

This ParameterException is thrown after the private key is recovered successfully when KeyStore.getCertificateChain(keyAlias) returns null or an empty array. A valid signing key entry must carry the certificate chain needed to build the APK signature; an alias without certificates cannot be used to sign.

Solutions

  1. Inspect the entry with 'keytool -list -v -keystore <keystoreFile> -alias <keyAlias>' and confirm it is a PrivateKeyEntry with a certificate chain.
  2. Re-generate the key with its certificate: 'keytool -genkeypair -alias <keyAlias> ...' so the entry includes the chain.
  3. If the key was imported without a cert, create/import the matching certificate: 'keytool -importcert -alias <keyAlias> -file cert.pem'.
  4. Double-check --ks-key-alias spelling; a similar alias may exist without certificates.

Example fix

// before: bare key import
keytool -importkeystore ... // key entry without certificate
// after
certtool --self-sign && keytool -importcert -alias release -file release.crt -keystore release.jks
Defensive patterns

Strategy: validation

Validate before calling

KeyStore ks = KeyStore.getInstance(new File(ksFile), ksPassword.toCharArray());
java.security.cert.Certificate[] chain = ks.getCertificateChain(alias);
Key key = ks.getKey(alias, keyPass.toCharArray());
if (key instanceof PrivateKey && (chain == null || chain.length == 0)) {
  throw new IllegalStateException("Entry " + alias + " has a private key but no certificate chain; re-export with its cert.");
}

Type guard

boolean isSignableEntry(KeyStore ks, String alias, char[] keyPass) throws Exception {
  java.security.cert.Certificate[] c = ks.getCertificateChain(alias);
  return ks.getKey(alias, keyPass) instanceof PrivateKey && c != null && c.length > 0;
}

Try / catch

try {
  signerParams.loadPrivateKeyAndCerts(passwordRetriever);
} catch (ParameterException e) {
  if (e.getMessage() != null && e.getMessage().endsWith("does not contain certificates")) {
    throw new IllegalStateException("Keystore entry lacks certificate chain - re-create with keytool -genkeypair", e);
  } throw e;
}

Prevention

When it happens

Trigger: loadPrivateKeyAndCertsFromKeyStore resolves the private key for --ks-key-alias, but the keystore entry under that alias holds only a raw key (e.g. a key imported without its certificate) or the alias actually points to a trusted-certificate-only entry with no private key chain.

Common situations: Importing a bare .key/PKCS#8 file into a keystore without 'keytool -importcert' for its certificate; aliases pointing to TrustedCertificateEntry rather than PrivateKeyEntry; corrupted or partially built keystores in CI caches.

Understand the failure class

Related errors


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

Appendix: source

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

          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) {
        throw new ParameterException("Private key file (--key) must be specified");
      }
      if (certFile == null) {
        throw new ParameterException("Certificate file (--cert) must be specified");
      }
      byte[] privateKeyBlob = readFully(new File(keyFile));

      PKCS8EncodedKeySpec keySpec;
      // Potentially encrypted key blob

View on GitHub (pinned to e4df245d82)