Partner MCP Error Reference
The @agentpress/sdk Partner MCP helpers throw two typed error classes. Map the reason field to your HTTP response per the tables below. All reasons are stable and exported as TypeScript string unions (PartnerTokenErrorReason, KeyRotationVerifyErrorReason).
For the integration-level usage context, see the Partner MCP Integration guide.
PartnerTokenError
Thrown by client.partners.verifyToken(token) when a Partner MCP Spec v1 JWT fails verification. Every reason maps to RFC 6750 401 invalid_token — use error_description to distinguish the specific failure. Do not leak internal details beyond the recommended descriptions below.
reason | error | error_description | Common cause |
|---|---|---|---|
signature_invalid | invalid_token | Signature verification failed | The JWT was signed with a key that doesn't match any entry in the JWKS, or the payload was tampered with after signing. |
issuer_mismatch | invalid_token | Issuer does not match | The iss claim does not match the issuer configured on the client — typically a staging token presented to the production verifier (or vice versa). |
audience_mismatch | invalid_token | Audience does not match | The aud claim does not match the audience configured on the client — the token was issued for a different partner's MCP URL. |
expired | invalid_token | Token expired | exp is in the past beyond the configured clock tolerance. Tokens have a 60-second TTL; AgentPress signs a fresh one per request. |
not_yet_valid | invalid_token | Token not yet valid | iat is in the future beyond the configured clock tolerance. Usually clock skew between your server and AgentPress. |
missing_claim | invalid_token | Required claim missing or invalid | One of sub, jti, scope, ext_provider, or iat is missing, empty, or the wrong type. Indicates a malformed issuer — should not occur against real AgentPress traffic. |
ext_provider_mismatch | invalid_token | ext_provider does not match | The ext_provider claim does not equal expectedExtProvider. Usually a configuration error — the client is pointed at the wrong partner identifier. |
algorithm_not_allowed | invalid_token | Algorithm not allowed | The JWT's alg header is not EdDSA. The SDK pins algorithms: ["EdDSA"] regardless of the token's header claim. |
kid_missing_or_unknown | invalid_token | Signing key id missing or unknown | The JWT header has no kid, or the kid does not resolve to any key in the JWKS. Common during the brief window immediately after a key rotation if you have not implemented the rotation webhook — resolve by forcing a JWKS refresh (client.partners.refreshJwks()) and retrying. |
malformed | invalid_token | Malformed token | The token is not a valid JWS compact-serialized JWT, or a generic decode error fell through to the catch-all. Typically means the Authorization header value is garbled or truncated. |
KeyRotationVerifyError
Thrown by client.webhooks.verifyKeyRotation({ payload, headers }) when a signing_key_rotation webhook fails HMAC, timestamp, or payload validation. HTTP mappings below are suggestions — adjust to your framework's conventions as long as non-2xx is returned (AgentPress retries on non-2xx with exponential backoff).
reason | HTTP | Recommended response body | Common cause |
|---|---|---|---|
invalid_signature | 401 | HMAC signature mismatch | The HMAC computed over the raw body with your configured webhookSecret does not match the X-AgentPress-Signature header. Usually a wrong secret, or the body was parsed/modified before verification (read the raw bytes, do not call .json() first). |
invalid_signature_format | 401 | Signature header missing or malformed | X-AgentPress-Signature is absent, does not start with sha256=, or the hex portion contains non-hex characters. |
timestamp_out_of_window | 401 | Timestamp outside allowed window | X-AgentPress-Timestamp is more than 5 minutes from the current time. Usually clock skew on your server; fix NTP and retry. |
invalid_timestamp | 401 | Invalid timestamp header | X-AgentPress-Timestamp is missing or is not a unix-seconds integer. |
payload_too_large | 413 | Payload too large | Request body exceeds the 8 KB cap. Legitimate rotation payloads are well under 1 KB, so this indicates a malformed or malicious request. |
malformed_payload | 400 | Malformed payload | Body is not valid JSON, or does not match the rotation event schema (missing event, wrong type, missing required string fields, etc.). |
Catching these errors
Both error classes extend AgentPressError, so you can catch them individually or catch the base class for a fallback. Import them from the SDK's top-level barrel.
import {
AgentPressError,
KeyRotationVerifyError,
PartnerTokenError,
} from "@agentpress/sdk";
try {
const claims = await client.partners.verifyToken(token);
// ...
} catch (err) {
if (err instanceof PartnerTokenError) {
// Typed err.reason — map to 401 invalid_token per the table above.
return respondUnauthorized(err.reason);
}
if (err instanceof AgentPressError) {
// Base class catch for any other SDK error (ConfigurationError, etc.).
return respondServerError(err.message);
}
throw err;
}The rotation webhook handler follows the same pattern — catch KeyRotationVerifyError to map typed reasons to the right HTTP response, and let anything else propagate:
try {
const event = client.webhooks.verifyKeyRotation({ payload, headers });
await client.partners.refreshJwks();
return respondOk();
} catch (err) {
if (err instanceof KeyRotationVerifyError) {
const status =
err.reason === "payload_too_large"
? 413
: err.reason === "malformed_payload"
? 400
: 401;
return respondWithStatus(status, err.message);
}
throw err;
}For the broader integration context (how to wire these errors into a Hono / Express / Worker handler), see the Partner MCP Integration guide.