{"record":{"id":"714e72ac04f9c922","repo":"mastra-ai/mastra","slug":"no-verification-key-was-provided-for-agent-card-si","errorCode":null,"errorMessage":"No verification key was provided for Agent Card signature verification","messagePattern":"No verification key was provided for Agent Card signature verification","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client-sdks/client-js/src/utils/verify-agent-card-signature.ts","lineNumber":133,"sourceCode":"        throw new Error('Agent Card signature is missing a protected \"alg\" header');\n      }\n\n      if (!allowedAlgorithms.includes(protectedHeader.alg)) {\n        throw new Error(`Agent Card signature algorithm \"${protectedHeader.alg}\" is not allowed`);\n      }\n\n      const verificationKey = await options.keyProvider({\n        agentCard,\n        signature,\n        protectedHeader,\n        alg: protectedHeader.alg,\n        kid: typeof protectedHeader.kid === 'string' ? protectedHeader.kid : undefined,\n        jku: typeof protectedHeader.jku === 'string' ? protectedHeader.jku : undefined,\n        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  );","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/client-sdks/client-js/src/utils/verify-agent-card-signature.ts#L115-L151","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nkeyProvider: async ({ kid }) => {\n  if (kid === 'old-key') return pem;\n}\n\n// after: fall back through all known keys\nkeyProvider: async ({ kid }) => {\n  const key = await jwks.get(kid);\n  if (key) return key;\n  console.warn('no key for kid', kid);\n  return null;\n}","handlingStrategy":"validation","validationCode":"// ensure the keyProvider resolves for the kid the server uses, BEFORE calling the API\nconst header = JSON.parse(atob(card.signatures[0].protected.replace(/-/g,'+').replace(/_/g,'/')));\nconst key = await keyProvider({ agentCard: card, signature: card.signatures[0], protectedHeader: header, kid: header.kid, index: 0 });\nif (!key) {\n  throw new Error(`no verification key registered for kid=${header.kid}; publish the signing public key first`);\n}","typeGuard":"function hasVerificationKey(k: unknown): k is NonNullable<AgentCardVerificationKey> {\n  return k !== null && k !== undefined;\n}","tryCatchPattern":"try {\n  await client.getAgentCard();\n} catch (e) {\n  if (e instanceof MastraClientError && e.message.includes('No verification key was provided')) {\n    await refreshKeyStore(); // reload JWKS / rotate cache, then retry\n  }\n}","preventionTips":["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."],"tags":["jws","key-management","kid-lookup","signature-verification"],"backgroundTag":"verification-key-not-found","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}