mastra-ai/mastra · error
No verification key was provided for Agent Card signature…
Error message
No verification key was provided for Agent Card signature verification
What it means
The library invokes the user-supplied options.keyProvider with the card, signature, protected header, and kid/jku/index. If it returns null or undefined, there is no key with which to verify the JWS, so it throws (per-signature) and ultimately aggregates into the verification-failed error. The keyProvider is entirely user code — this error means your key-lookup logic didn't produce a key.
Solutions
- Log the keyProvider input (kid/alg/jku/index) and verify your key store actually contains a key with that kid.
- Return a key from the keyProvider for every expected kid — export the signing public key into your JWKS/KeyVault and map kid → PEM/JWK.
- Fix accidental `keyProvider: async (input) => { fetchKey(input.kid) }` — missing return returns undefined; add `return`.
- Refresh/rotate the verifier's key cache so newly rotated server keys are visible.
Example fix
// before
keyProvider: async ({ kid }) => {
if (kid === 'old-key') return pem;
}
// after: fall back through all known keys
keyProvider: async ({ kid }) => {
const key = await jwks.get(kid);
if (key) return key;
console.warn('no key for kid', kid);
return null;
} Defensive patterns
Strategy: validation
Validate before calling
// ensure the keyProvider resolves for the kid the server uses, BEFORE calling the API
const header = JSON.parse(atob(card.signatures[0].protected.replace(/-/g,'+').replace(/_/g,'/')));
const key = await keyProvider({ agentCard: card, signature: card.signatures[0], protectedHeader: header, kid: header.kid, index: 0 });
if (!key) {
throw new Error(`no verification key registered for kid=${header.kid}; publish the signing public key first`);
} Type guard
function hasVerificationKey(k: unknown): k is NonNullable<AgentCardVerificationKey> {
return k !== null && k !== undefined;
} Try / catch
try {
await client.getAgentCard();
} catch (e) {
if (e instanceof MastraClientError && e.message.includes('No verification key was provided')) {
await refreshKeyStore(); // reload JWKS / rotate cache, then retry
}
} Prevention
- Register every signing key's public counterpart under the kid embedded in the JWS header.
- Always `return` the key from the keyProvider (a missing return in an async fn yields undefined).
- Refresh the JWKS cache on key rotation and on kid-miss.
- Verify keyProvider behavior with unit tests covering known and unknown kids.
When it happens
Trigger: getAgentCard() with verification enabled where keyProvider returns null/undefined — e.g. the JWS header's `kid` doesn't match any key in your JWKS/key store, the keyProvider filters on alg the header doesn't match, or the provider isn't async and forgets to return the key.
Common situations: kid mismatch between server signing key and the keys published in your JWKS; keys rotated on the server but the verifier caches old keys; jku URL fetch failing silently and the provider returning null; forgetting to return the key in a synchronous keyProvider arrow function.
Related errors
- A2A Agent Card signature verification failed
- Agent Card signature algorithm
- Agent Card signature is missing a protected "alg" header
- Expected a PEM-encoded public key or certificate string for…
- [FactorySecretEncryption] Unable to decrypt encrypted value.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/714e72ac04f9c922.
Report an issue: GitHub.
Appendix: source
Thrown at client-sdks/client-js/src/utils/verify-agent-card-signature.ts:133
throw new Error('Agent Card signature is missing a protected "alg" header');
}
if (!allowedAlgorithms.includes(protectedHeader.alg)) {
throw new Error(`Agent Card signature algorithm "${protectedHeader.alg}" is not allowed`);
}
const verificationKey = await options.keyProvider({
agentCard,
signature,
protectedHeader,
alg: protectedHeader.alg,
kid: typeof protectedHeader.kid === 'string' ? protectedHeader.kid : undefined,
jku: typeof protectedHeader.jku === 'string' ? protectedHeader.jku : undefined,
index,
});
if (!verificationKey) {
throw new Error('No verification key was provided for Agent Card signature verification');
}
const importedKey = await importVerificationKey(verificationKey, protectedHeader.alg);
await compactVerify(compactJws, importedKey, {
algorithms: allowedAlgorithms,
});
return agentCard;
} catch (error) {
verificationErrors.push(error instanceof Error ? error.message : 'Unknown verification failure');
}
}
throw new MastraClientError(
200,
'OK',
`A2A Agent Card signature verification failed: ${verificationErrors.join('; ')}`,
);View on GitHub (pinned to 75dd419e61)