Every tool error uses a consistent shape: isError: true, a human-readable text field the AI can surface to the user, and a machine-readable error_code in _meta for programmatic branching.
{
"content": [
{ "type": "text", "text": "You've run out of lookup credits. Visit your RocketReach account to add more." }
],
"_meta": { "error_code": "insufficient_credits", "credit_type": "standard_lookup" },
"isError": true
}Error codes
error_code | HTTP equivalent | When it happens |
|---|---|---|
auth_required | 401 | No Bearer token, expired token, wrong audience, or v2 rejected the request based on user state (unverified email, suspended account, etc.) |
insufficient_credits | 402 | The credit type required for this operation has a zero balance — either depleted or never issued on the account. See the credit_type extra field to know which type failed |
not_found | 404 | The supplied identifier did not resolve to any profile or company |
lookup_failed | — | The profile resolved, the search ran to completion, but no contact information was found. Terminal — retrying the same identifier will not help |
rate_limited | 429 | RocketReach API rate limit reached. Check retry_after_seconds in _meta |
validation_error | 400 | A parameter failed input validation. Check field and reason in _meta |
service_error | 5xx | Unexpected backend failure. Retry after a moment |
Extra fields in _meta
_meta| Code | Extra fields | Example |
|---|---|---|
insufficient_credits | credit_type — which of the six credit types was missing: standard_lookup, premium_lookup, phone_lookup, person_enrich, person_export, company_export | { "error_code": "insufficient_credits", "credit_type": "company_export" } |
rate_limited | retry_after_seconds — how long to wait before retrying | { "error_code": "rate_limited", "retry_after_seconds": 30 } |
validation_error | field — which parameter failed; reason — human-readable explanation | { "error_code": "validation_error", "field": "email", "reason": "must be a valid email address" } |
Non-error responses
One intermediate state looks like an error but is not — isError is false.
status: "pending" — the lookup is still in progress. Call check_person_status with the profile_id to retrieve results once ready. No credit is consumed on the poll.
auth_required detail
auth_required detailauth_required covers two distinct cases:
- Token missing or invalid — no Bearer token in the request, the token is expired, the audience does not match the MCP server URL, or the token was signed with an unrecognized key. The client should re-authorize.
- User state blocked — the token is cryptographically valid but v2 rejected the request because of account state: email not verified, account suspended, or region unavailable. The error text describes which gate blocked the request and what the user should do.
Notes for custom client builders
Error messages in content[0].text are user-readable — surface them to the end user as-is. Do not parse the text for machine logic; use _meta.error_code instead.
lookup_failed and not_found are terminal — retrying the same identifier will not produce a different result. Log or surface the message and move on.
Per-record status: "failed" from check_person_status (when called with an array of profile IDs) is not a tool-level error — the array itself is returned as a success, and individual records that failed to resolve carry status: "failed" inside the array.
