{"record":{"id":"e980831504f55713","repo":"shwenzhang/AndResGuard","slug":"neither-keystore-key-alias-nor-private-key-file-available","errorCode":null,"errorMessage":"Neither KeyStore key alias nor private key file available","messagePattern":"Neither KeyStore key alias nor private key file available","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java","lineNumber":246,"sourceCode":"          e.printStackTrace();\n          System.exit(2);\n          return;\n        }\n        String v1SigBasename;\n        if (signer.v1SigFileBasename != null) {\n          v1SigBasename = signer.v1SigFileBasename;\n        } else if (signer.keystoreKeyAlias != null) {\n          v1SigBasename = signer.keystoreKeyAlias;\n        } else if (signer.keyFile != null) {\n          String keyFileName = new File(signer.keyFile).getName();\n          int delimiterIndex = keyFileName.indexOf('.');\n          if (delimiterIndex == -1) {\n            v1SigBasename = keyFileName;\n          } else {\n            v1SigBasename = keyFileName.substring(0, delimiterIndex);\n          }\n        } else {\n          throw new RuntimeException(\"Neither KeyStore key alias nor private key file available\");\n        }\n        ApkSigner.SignerConfig signerConfig = new ApkSigner.SignerConfig.Builder(v1SigBasename,\n            signer.privateKey,\n            signer.certs\n        ).build();\n        signerConfigs.add(signerConfig);\n      }\n    }\n\n    if (outputApk == null) {\n      outputApk = inputApk;\n    }\n    File tmpOutputApk;\n    if (inputApk.getCanonicalPath().equals(outputApk.getCanonicalPath())) {\n      tmpOutputApk = File.createTempFile(\"apksigner\", \".apk\");\n      tmpOutputApk.deleteOnExit();\n    } else {\n      tmpOutputApk = outputApk;","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/shwenzhang/AndResGuard/blob/e4df245d82f27d9a2d0dd108260a3510cbaba849/AndResGuard-core/src/main/java/apksigner/ApkSignerTool.java#L228-L264","documentation":"When deriving the v1 (JAR) signature file basename, the tool uses --v1-signer-name, then the keystore alias, then the key file name. If none of these is available it throws this RuntimeException — an internal invariant, since any loaded signer should have one.","triggerScenarios":"A signer loaded without keystoreKeyAlias and without keyFile (e.g. keystore path existed but alias resolution left both null), while --v1-signer-name was not provided.","commonSituations":"Custom/patched builds of the tool; providing certs in unusual ways; alias passed via a mechanism the tool didn't record (e.g. alias with different case handling).","solutions":["Add --v1-signer-name <basename> explicitly","Ensure --ks-key-alias is passed alongside --ks","Or supply the key via --key so the file name can be used"],"exampleFix":"// before\napksigner sign --ks ks.jks --ks-pass env:KS app.apk\n// after\napksigner sign --ks ks.jks --ks-key-alias release --ks-pass env:KS app.apk","handlingStrategy":"validation","validationCode":"boolean hasAliasOrKey = Arrays.asList(args).contains(\"--ks-key-alias\") || Arrays.asList(args).contains(\"--key\");\nif (!hasAliasOrKey) throw new IllegalArgumentException(\"Provide --ks-key-alias (or --key), or --v1-signer-name\");","typeGuard":null,"tryCatchPattern":"try { signCmd(args); } catch (RuntimeException e) { System.err.println(e.getMessage()); exit(2); }","preventionTips":["Always pass --ks-key-alias with --ks","Or set --v1-signer-name explicitly for deterministic signature file names","Avoid patched/custom builds of the tool"],"tags":["signing","invariant"],"backgroundTag":"internal-invariant-violation","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"}