shwenzhang/AndResGuard · error · ParameterException

At least one signer must be specified

Error message

At least one signer must be specified

What it means

Validation guard in ApkSignerTool.sign: after parsing all --ks/--key/--cert options, no signer configuration was assembled. apksigner refuses to run because signing is impossible without at least one private key/certificate pair. Fires when the user omits --ks/--key or provides only non-signer options like --in, --out, or --min-sdk-version.

Solutions

  1. Add signer options: --ks <keystore> --ks-key-alias <alias> (plus passwords)
  2. Or use raw files: --key <pk8> --cert <pem>
  3. Verify the script actually passes the keystore variables (quote/echo them)

Example fix

// before
apksigner sign --in app.apk --out app-signed.apk
// after
apksigner sign --ks release.jks --ks-key-alias release --ks-pass env:KS_PASS --in app.apk --out app-signed.apk
Defensive patterns

Strategy: validation

Validate before calling

boolean hasSigner = false;
for (String a : args) {
    if (a.equals("--ks") || a.equals("--key") || a.equals("--ks-key-alias") || a.equals("--next-signer")) { hasSigner = true; break; }
}
if (!hasSigner) throw new IllegalArgumentException("sign requires --ks/--ks-key-alias or --key/--cert");

Try / catch

try { signCmd(args); } catch (ParameterException e) { System.err.println("Missing signer config: " + e.getMessage()); exit(1); }

Prevention

When it happens

Trigger: Running `apksigner sign --in app.apk --out out.apk` with no --ks, --ks-key-alias, or --key/--cert options; or providing only --next-signer separators without any actual signer data.

Common situations: Forgetting keystore options entirely; assuming a default debug keystore is picked up automatically (it is not); scripts that drop --ks arguments when variables are empty.

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/0e9111f73e4b33aa. Report an issue: GitHub.

Appendix: source

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

        signerParams.keyFile = optionsParser.getRequiredValue("Private key file");
      } else if ("cert".equals(optionName)) {
        signerParams.certFile = optionsParser.getRequiredValue("Certificate file");
      } else if (("v".equals(optionName)) || ("verbose".equals(optionName))) {
        verbose = optionsParser.getOptionalBooleanValue(true);
      } else {
        throw new ParameterException("Unsupported option: "
                                     + optionOriginalForm
                                     + ". See --help for supported"
                                     + " options.");
      }
    }
    if (!signerParams.isEmpty()) {
      signers.add(signerParams);
    }
    signerParams = null;

    if (signers.isEmpty()) {
      throw new ParameterException("At least one signer must be specified");
    }

    params = optionsParser.getRemainingParams();
    if (inputApk != null) {
      // Input APK has been specified via preceding parameters. We don't expect any more
      // parameters.
      if (params.length > 0) {
        throw new ParameterException("Unexpected parameter(s) after " + optionOriginalForm + ": " + params[0]);
      }
    } else {
      // Input APK has not been specified via preceding parameters. The next parameter is
      // supposed to be the path to input APK.
      if (params.length < 1) {
        throw new ParameterException("Missing input APK");
      } else if (params.length > 1) {
        throw new ParameterException("Unexpected parameter(s) after input APK (" + params[1] + ")");
      }
      inputApk = new File(params[0]);

View on GitHub (pinned to e4df245d82)