mastra-ai/mastra · error · MastraClientError
A2A Agent Card signature verification failed: ${verification
Error message
A2A Agent Card signature verification failed: ${verificationErrors.join('; ')} What it means
This is the aggregate error thrown when every signature on the Agent Card failed verification. Each per-signature failure (missing alg, disallowed alg, missing key, import failure, or compactVerify signature mismatch) is collected into verificationErrors and joined with '; '. If any single signature had verified, the card would have been returned early — reaching here means none did.
Source
Thrown at client-sdks/client-js/src/utils/verify-agent-card-signature.ts:147
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)
Solutions
- Read the joined sub-errors in the message to identify the concrete per-signature cause (missing key vs disallowed alg vs crypto mismatch).
- Confirm the public key returned by your keyProvider is the exact pair of the server's signing private key.
- Ensure the server signs the card and does not modify it afterwards — the signature covers canonicalize(card minus signatures).
- Align @mastra/core (server signer) and client-js versions so canonicalization and defaults match.
- As a diagnostic, verify the detached JWS manually with jose against the canonicalized card to isolate the failing component.
Example fix
// before: stale public key after server rotation
const client = new MastraClient({ baseUrl, verifyAgentCardSignature: { keyProvider: () => oldPem } });
// after: resolve the current key by kid
const client = new MastraClient({ baseUrl, verifyAgentCardSignature: { keyProvider: async ({ kid }) => await jwks.getByKid(kid) } }); Defensive patterns
Strategy: try-catch
Validate before calling
// pre-flight: check at least one signature looks verifiable before trusting the card
if (card.signatures?.length && !keyStoreCoversKids(card.signatures.map(s => decodeHeader(s.protected).kid))) {
console.warn('Agent Card signatures cannot be verified with current keys');
} Type guard
function isMastraClientError(e: unknown): e is MastraClientError {
return e instanceof MastraClientError;
} Try / catch
let agentCard;
try {
agentCard = await client.getAgentCard();
} catch (e) {
if (e instanceof MastraClientError && e.message.startsWith('A2A Agent Card signature verification failed')) {
// inspect e.message sub-errors; decide: fail closed (rethrow) or fetch unsigned card
throw e;
}
throw e;
} Prevention
- Never modify the Agent Card between signing and serving — the signature covers the canonicalized unsigned card.
- Keep the verifier's public keys in sync with the server's signing keys and rotate them together.
- Match @mastra/core and client-js versions so canonicalization is identical on both sides.
- Parse the ';'-joined sub-errors in the message to pinpoint the root cause before changing config.
- Add an integration test that signs a card server-side and verifies it with the same client options used in production.
When it happens
Trigger: getAgentCard() with verification enabled where the card carries signatures but compactVerify fails for all of them — typically the canonical payload doesn't match what was signed, the key is wrong (different key than the signer's private counterpart), or every signature hits one of the per-signature errors (215-218 family).
Common situations: Server mutates the card after signing (adding fields) so the payload no longer matches; verifier holds the wrong public key or a certificate for a different issuer; the server and client canonicalize differently (version mismatch); clock/key rotation races after a deploy.
Related errors
- Agent Card signature is missing a protected "alg" header
- Agent Card signature algorithm "${protectedHeader.alg}" is n
- Expected a PEM-encoded public key or certificate string for
- Failed to canonicalize A2A Agent Card for signature verifica
- No verification key was provided for Agent Card signature ve
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/055b5ad4cb59cb22.
Report an issue: GitHub.