{"record":{"id":"055b5ad4cb59cb22","repo":"mastra-ai/mastra","slug":"a2a-agent-card-signature-verification-failed-ve","errorCode":null,"errorMessage":"A2A Agent Card signature verification failed: ${verificationErrors.join('; ')}","messagePattern":"A2A Agent Card signature verification failed: (.+?)","errorType":"exception","errorClass":"MastraClientError","httpStatus":200,"severity":"error","filePath":"client-sdks/client-js/src/utils/verify-agent-card-signature.ts","lineNumber":147,"sourceCode":"        index,\n      });\n\n      if (!verificationKey) {\n        throw new Error('No verification key was provided for Agent Card signature verification');\n      }\n\n      const importedKey = await importVerificationKey(verificationKey, protectedHeader.alg);\n      await compactVerify(compactJws, importedKey, {\n        algorithms: allowedAlgorithms,\n      });\n\n      return agentCard;\n    } catch (error) {\n      verificationErrors.push(error instanceof Error ? error.message : 'Unknown verification failure');\n    }\n  }\n\n  throw new MastraClientError(\n    200,\n    'OK',\n    `A2A Agent Card signature verification failed: ${verificationErrors.join('; ')}`,\n  );\n}\n","sourceCodeStart":129,"sourceCodeEnd":153,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/client-sdks/client-js/src/utils/verify-agent-card-signature.ts#L129-L153","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before: stale public key after server rotation\nconst client = new MastraClient({ baseUrl, verifyAgentCardSignature: { keyProvider: () => oldPem } });\n\n// after: resolve the current key by kid\nconst client = new MastraClient({ baseUrl, verifyAgentCardSignature: { keyProvider: async ({ kid }) => await jwks.getByKid(kid) } });","handlingStrategy":"try-catch","validationCode":"// pre-flight: check at least one signature looks verifiable before trusting the card\nif (card.signatures?.length && !keyStoreCoversKids(card.signatures.map(s => decodeHeader(s.protected).kid))) {\n  console.warn('Agent Card signatures cannot be verified with current keys');\n}","typeGuard":"function isMastraClientError(e: unknown): e is MastraClientError {\n  return e instanceof MastraClientError;\n}","tryCatchPattern":"let agentCard;\ntry {\n  agentCard = await client.getAgentCard();\n} catch (e) {\n  if (e instanceof MastraClientError && e.message.startsWith('A2A Agent Card signature verification failed')) {\n    // inspect e.message sub-errors; decide: fail closed (rethrow) or fetch unsigned card\n    throw e;\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["jws","signature-mismatch","agent-card","signature-verification"],"backgroundTag":"signature-verification-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}