shwenzhang/AndResGuard · error · ParameterException

KeyStore (--ks) must be specified

Error message

KeyStore (--ks) must be specified

What it means

loadPrivateKeyAndCertsFromKeyStore requires keystoreFile to be non-null; this is a defensive re-check of the invariant already established by the caller (loadPrivateKeyAndCerts only routes here when keystoreFile != null). It fires only if the method is invoked directly with no keystore configured.

Solutions

  1. Set the keystoreFile (--ks) before invoking KeyStore-based credential loading.
  2. Use loadPrivateKeyAndCerts instead so the correct branch is chosen automatically.
  3. If patching the tool, keep the ksType == null guard consistent with the caller's dispatch.

Example fix

// before
signerConfig.loadPrivateKeyAndCertsFromKeyStore(retriever); // keystoreFile null
// after
signerConfig.keystoreFile = new File("release.jks");
signerConfig.loadPrivateKeyAndCertsFromKeyStore(retriever);
Defensive patterns

Strategy: validation

Validate before calling

// Java: check before calling KeyStore-based loading
if (keystoreFile == null) {
    throw new IllegalArgumentException("--ks must be set before KeyStore credential loading");
}

Prevention

When it happens

Trigger: Calling loadPrivateKeyAndCertsFromKeyStore programmatically (or a code change breaking the routing) while keystoreFile is null; normally unreachable via the CLI because loadPrivateKeyAndCerts guards the branch.

Common situations: Custom tooling built on ApkSignerTool internals calling the private method or building a SignerConfig without a keystore; refactoring that changed the dispatch logic.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

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

    private void loadPrivateKeyAndCerts(PasswordRetriever passwordRetriever) throws Exception {
      if (keystoreFile != null) {
        if (keyFile != null) {
          throw new ParameterException("--ks and --key may not be specified at the same time");
        } else if (certFile != null) {
          throw new ParameterException("--ks and --cert may not be specified at the same time");
        }
        loadPrivateKeyAndCertsFromKeyStore(passwordRetriever);
      } else if (keyFile != null) {
        loadPrivateKeyAndCertsFromFiles(passwordRetriever);
      } else {
        throw new ParameterException("KeyStore (--ks) or private key file (--key) must be specified");
      }
    }

    private void loadPrivateKeyAndCertsFromKeyStore(PasswordRetriever passwordRetriever) throws Exception {
      if (keystoreFile == null) {
        throw new ParameterException("KeyStore (--ks) must be specified");
      }

      // 1. Obtain a KeyStore implementation
      String ksType = (keystoreType != null) ? keystoreType : KeyStore.getDefaultType();
      KeyStore ks;
      if (keystoreProviderName != null) {
        // Use a named Provider (assumes the provider is already installed)
        ks = KeyStore.getInstance(ksType, keystoreProviderName);
      } else if (keystoreProviderClass != null) {
        // Use a new Provider instance (does not require the provider to be installed)
        Class<?> ksProviderClass = Class.forName(keystoreProviderClass);
        if (!Provider.class.isAssignableFrom(ksProviderClass)) {
          throw new ParameterException("Keystore Provider class "
                                       + keystoreProviderClass
                                       + " not subclass of "
                                       + Provider.class.getName());
        }
        Provider ksProvider;

View on GitHub (pinned to e4df245d82)