{"record":{"id":"280219c0232c6ea4","repo":"shwenzhang/AndResGuard","slug":"private-key-file-key-must-be-specified","errorCode":null,"errorMessage":"Private key file (--key) must be specified","messagePattern":"Private key file \\(--key\\) must be specified","errorType":"validation","errorClass":"ParameterException","httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java","lineNumber":779,"sourceCode":"                              + keyAlias\n                              + \"\\\" from \"\n                              + keystoreFile\n                              + \". Wrong password?\", e);\n      }\n      this.privateKey = key;\n      Certificate[] certChain = ks.getCertificateChain(keyAlias);\n      if ((certChain == null) || (certChain.length == 0)) {\n        throw new ParameterException(keystoreFile + \" entry \\\"\" + keyAlias + \"\\\" does not contain certificates\");\n      }\n      this.certs = new ArrayList<>(certChain.length);\n      for (Certificate cert : certChain) {\n        this.certs.add((X509Certificate) cert);\n      }\n    }\n\n    private void loadPrivateKeyAndCertsFromFiles(PasswordRetriever passwordRetriver) throws Exception {\n      if (keyFile == null) {\n        throw new ParameterException(\"Private key file (--key) must be specified\");\n      }\n      if (certFile == null) {\n        throw new ParameterException(\"Certificate file (--cert) must be specified\");\n      }\n      byte[] privateKeyBlob = readFully(new File(keyFile));\n\n      PKCS8EncodedKeySpec keySpec;\n      // Potentially encrypted key blob\n      try {\n        EncryptedPrivateKeyInfo encryptedPrivateKeyInfo = new EncryptedPrivateKeyInfo(privateKeyBlob);\n\n        // The blob is indeed an encrypted private key blob\n        String passwordSpec = (keyPasswordSpec != null) ? keyPasswordSpec : PasswordRetriever.SPEC_STDIN;\n        List<char[]> keyPasswords = passwordRetriver.getPasswords(passwordSpec, \"Private key password for \" + name);\n        keySpec = decryptPkcs8EncodedKey(encryptedPrivateKeyInfo, keyPasswords);\n      } catch (IOException e) {\n        // The blob is not an encrypted private key blob\n        if (keyPasswordSpec == null) {","sourceCodeStart":761,"sourceCodeEnd":797,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java#L761-L797","documentation":"This ParameterException is thrown by loadPrivateKeyAndCertsFromFiles when the raw private key path (--key) was not provided. This code path runs when signing is configured to read the key from PEM/PKCS#8 files instead of a keystore, and a null keyFile makes signing impossible.","triggerScenarios":"Invoking the signer with file-based signing (no --ks) but omitting the --key argument; programmatically constructing SignerParams with certFile set but keyFile left null.","commonSituations":"Switching a build from keystore-based to file-based signing and forgetting --key; shell scripts where a KEY_PATH variable is empty; docs examples showing only --cert.","solutions":["Pass the private key file: add --key /path/to/private_key.pk8 (or PEM) to the command.","If you actually intended keystore-based signing, pass --ks <keystore> --ks-key-alias <alias> instead.","Check the wrapper script/env for an unset KEY variable (e.g. \"$KEY_PATH\" expanding to nothing)."],"exampleFix":"// before\napksigner sign --cert cert.pem --out signed.apk unsigned.apk\n// after\napksigner sign --key private_key.pk8 --cert cert.pem --out signed.apk unsigned.apk","handlingStrategy":"validation","validationCode":"File keyFile = new File(keyPath);\nif (keyPath == null || keyPath.isEmpty() || !keyFile.isFile()) {\n  throw new IllegalArgumentException(\"--key must point to an existing private key file (PKCS#8/PEM)\");\n}","typeGuard":null,"tryCatchPattern":"try {\n  signerParams.loadPrivateKeyAndCerts(passwordRetriever);\n} catch (ParameterException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"--key) must be specified\")) {\n    throw new IllegalArgumentException(\"Provide --key <private key file> for file-based signing, or --ks for keystore signing\", e);\n  } throw e;\n}","preventionTips":["Fail fast in build scripts: assert the key path variable is non-empty before invoking the signer.","Decide explicitly between keystore mode (--ks) and file mode (--key/--cert); never mix partially.","Keep signing commands in versioned scripts rather than ad-hoc shell history."],"tags":["signing","cli-argument","missing-argument","android"],"backgroundTag":"missing-required-argument","analyzedSha":"e4df245d82f27d9a2d0dd108260a3510cbaba849","analyzedAt":"2026-09-12T17:49:07.798Z","contentChangedAt":"2026-09-12T17:49:07.798Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}