arduino/Arduino · error · IllegalArgumentException

Can't find encryption key in key ring.

Error message

Can't find encryption key in key ring.

What it means

GPGDetachedSignatureVerifier.readPublicKey() scans a BouncyCastle key ring for a public key whose key ID (hex, upper-case) ends with the requested id suffix. If no key matches, it throws an IllegalArgumentException saying the encryption (verification) key is absent from the key ring.

Source

Thrown at arduino-core/src/cc/arduino/contributions/GPGDetachedSignatureVerifier.java:115

  private PGPPublicKey readPublicKey(InputStream input, String id) throws IOException, PGPException {
    PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(PGPUtil.getDecoderStream(input), new BcKeyFingerprintCalculator());

    Iterator<PGPPublicKeyRing> keyRingIter = pgpPub.getKeyRings();
    while (keyRingIter.hasNext()) {
      PGPPublicKeyRing keyRing = keyRingIter.next();

      Iterator<PGPPublicKey> keyIter = keyRing.getPublicKeys();
      while (keyIter.hasNext()) {
        PGPPublicKey key = keyIter.next();

        if (Long.toHexString(key.getKeyID()).toUpperCase().endsWith(id)) {
          return key;
        }
      }
    }

    throw new IllegalArgumentException("Can't find encryption key in key ring.");
  }

}

View on GitHub (pinned to a0df6e0e83)

Solutions

  1. Update to a version of arduino-core/IDE that bundles the current Arduino signing key ring.
  2. Import the signer's public key into the key ring used by GPGDetachedSignatureVerifier.
  3. Check that the requested key id suffix is correct and refers to a key actually in the ring (note the suffix, not full id, matching rule).
  4. If the index is third-party, add its key to the trusted key ring or skip signature verification consciously.

Example fix

// before
verifier.verify(indexFile, signatureFile, verifier.readPublicKey("OLDKEYID"));
// after
String keyId = "NEWKEYIDSUFFIX"; // from the updated bundled keyring
PublicKey key = verifier.readPublicKey(keyId); // throws if ring outdated -> refresh keys first
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the key ring contains a key with the requested id before verifying
PGPPublicKey k = findKeyByIdSuffix(keyRing, keyIdSuffix);
if (k == null) { throw new IllegalStateException("Key " + keyIdSuffix + " missing from ring; update signing keys first"); }

Try / catch

try { verify(index, sig, key); } catch (IllegalArgumentException e) { if (e.getMessage().contains("Can't find encryption key")) { refreshTrustedKeyRing(); } else { throw e; } }

Prevention

When it happens

Trigger: readPublicKey (invoked during signature verification of package indexes) is asked for key id 'id' but no key in the loaded key ring's long key id hex ends with that suffix — e.g. an outdated bundled key ring missing the signer's key, or an id lookup that assumes a suffix match on a rotated key.

Common situations: Package index signed with a newer Arduino signing key while the local key ring only contains the old key; manually replaced or stale Arduino.cgx/keyring resources; verifying indexes signed by third parties whose keys were never imported.

Understand the failure class

Background: "API key is required" / "API key not found" / "No API key was set": the missing-api-key error family across 16 libraries — this error's family across 16 libraries.

Related errors


AI-assisted analysis of arduino/Arduino@a0df6e0e83 (2026-09-06). Data as JSON: /api/errors/91d9f53773f5f790. Report an issue: GitHub.