{"record":{"id":"b25a6033e74f4334","repo":"gradle/gradle","slug":"cannot-find-key-with-id-s-in-key-data","errorCode":null,"errorMessage":"Cannot find key with id '%s' in key data","messagePattern":"Cannot find key with id '(.+?)' in key data","errorType":"exception","errorClass":"InvalidUserDataException","httpStatus":null,"severity":"error","filePath":"platforms/software/signing/src/main/java/org/gradle/plugins/signing/signatory/internal/pgp/PgpSignatoryUtil.java","lineNumber":178,"sourceCode":"     * The {@code keyData} may contain one or more master keys with subkeys.\n     * If there is more than one master key or a subkey is needed, the {@code keyId} must be provided.\n     * If omitted, the keyData is treated as a single master key (with subkeys) and the master secret key is returned.\n     *\n     * @param keyId the id of the key, can be null to return the only master secret key\n     * @param keyData the ASCII-armored representation of the key\n     * @return the parsed secret key\n     */\n    public static PGPSecretKey parseSecretKey(@Nullable String keyId, String keyData) {\n        try (InputStream in = PGPUtil.getDecoderStream(new ByteArrayInputStream(keyData.getBytes(UTF_8)))) {\n            if (keyId == null) {\n                return new JcaPGPSecretKeyRing(in).getSecretKey();\n            } else {\n                PgpKeyId expectedKeyId = new PgpKeyId(keyId);\n                PGPSecretKey key = findSecretKey(new JcaPGPSecretKeyRingCollection(in), expectedKeyId);\n                if (key != null) {\n                    return key;\n                }\n                throw new InvalidUserDataException(String.format(\"Cannot find key with id '%s' in key data\",  keyId));\n            }\n        } catch (IOException | PGPException e) {\n            throw new InvalidUserDataException(\"Could not read PGP secret key\", e);\n        }\n    }\n}\n","sourceCodeStart":160,"sourceCodeEnd":185,"githubUrl":"https://github.com/gradle/gradle/blob/534f27719b66953f95cc907aae7f2c1b12f5482d/platforms/software/signing/src/main/java/org/gradle/plugins/signing/signatory/internal/pgp/PgpSignatoryUtil.java#L160-L185","documentation":"PgpSignatoryUtil.parseSecretKey parses in-memory key data (the string form used by in-memory signatories). When a keyId is supplied, it searches the parsed ring for that id; no match throws InvalidUserDataException 'Cannot find key with id ... in key data'. The key data parsed fine but does not contain the requested key.","triggerScenarios":"useInMemoryPgpKeys(keyId, secretKey, password) where keyId does not match any (sub)key inside secretKey; using the long 64-bit id while the data's primary key has a different short id; trailing whitespace altering the id string.","commonSituations":"CI secrets drift: the key env var was rotated but the key id variable was not; copying a key id from documentation instead of from the actual exported key; multiple subkeys causing id confusion.","solutions":["Derive the id from the actual key material you inject: gpg --list-packets on the exported armored key shows key IDs","Re-sync CI variables so keyId and secretKey come from the same key export","If the data holds exactly one key, use the form without a keyId so the primary key is taken implicitly","Verify the id format: 8 hex chars or 0x + 8 hex chars"],"exampleFix":"# before\nsigning {\n    inMemoryPgp 'release', '1A2B3C4D', secretKey, password // id not in secretKey\n}\n\n# after\ngpg --list-packets secretKey.asc | grep 'keyid' # e.g. keyid 00B5050F\nsigning {\n    inMemoryPgp 'release', '00B5050F', secretKey, password\n}","handlingStrategy":"try-catch","validationCode":"def ids = [] as Set\nnew BcPGPSecretKeyRingCollection(PGPUtil.getDecoderStream(new ByteArrayInputStream(keyData.bytes))).keyRings.each { r ->\n    r.secretKeys.each { k -> ids << PgpKeyId.toHex(k.keyID) }\n}\nassert keyId in ids : \"keyId ${keyId} not in key data; found ${ids}\"","typeGuard":null,"tryCatchPattern":"try {\n    def key = PgpSignatoryUtil.parseSecretKey(keyId, keyData)\n} catch (InvalidUserDataException e) {\n    throw new GradleException(\"keyId does not match the injected secretKey; re-sync CI variables\", e)\n}","preventionTips":["Treat keyId + secretKey + password as one rotated unit, stored together","When the key data has exactly one key, omit the keyId so the primary key is used implicitly","Add a pipeline step that runs gpg --list-packets on the secret before the build"],"tags":["gradle","signing","pgp","key-not-found","in-memory"],"backgroundTag":"pgp-key-not-found","analyzedSha":"534f27719b66953f95cc907aae7f2c1b12f5482d","analyzedAt":"2026-08-22T08:09:12.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}