mastra-ai/mastra · error

No verification key was provided for Agent Card signature ve

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.

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)

Solutions

  1. Log the keyProvider input (kid/alg/jku/index) and verify your key store actually contains a key with that kid.
  2. Return a key from the keyProvider for every expected kid — export the signing public key into your JWKS/KeyVault and map kid → PEM/JWK.
  3. Fix accidental `keyProvider: async (input) => { fetchKey(input.kid) }` — missing return returns undefined; add `return`.
  4. 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

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


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/714e72ac04f9c922. Report an issue: GitHub.