Skip to content

Errors & troubleshooting

Every error response follows the JSON-RPC 2.0 envelope:

json
{
  "jsonrpc": "2.0",
  "id": 1,
  "error": {
    "code": -32004,
    "message": "Human-readable description",
    "data": { "type": "tier_required", "retryable": false, "action": "https://app.adcommand.io/billing" }
  }
}

The HTTP status code is also set (401 / 402 / 404 / 429 / 500 etc.) for tools that filter by status without parsing JSON.

error.data (machine-readable, optional). Actionable errors include a data object so your agent can branch on the failure without parsing the message string:

FieldMeaning
typeOne of unknown_tool, tier_required, insufficient_credits, rate_limited, invalid_input, upstream_error, internal_error
retryabletrue if retrying the same call later may succeed (transient / rate-limited)
retryAfterSecondsWhen retryable, how long to wait before retrying
actionA URL or short instruction to resolve it (e.g. the billing page)

Auth errors (401)

CodeMessageCauseFix
-32001Missing Authorization: Bearer headerNo Authorization header in the requestRe-check ~/.claude.json formatting
-32001Invalid key format (must start with ac_)Auth header doesn't start with ac_Re-paste the cleartext key from the email or Settings dialog
-32001Invalid or revoked keyKey not found, revoked, or expired in mcp_api_keysCheck key status at Settings → API Keys; mint a new one if revoked

Rate / tier / quota errors (429)

CodeMessageCauseFix
-32002Rate limit exceeded. Retry after Ns.More than 60 calls/min on this single keyWait the suggested seconds, or split traffic across multiple keys
-32003Daily credit cap reached (X/Y credits in last 24h on TIER tier).Per-tier daily cap: Starter 1500, Pro 5000, Agency 15000Rolls off automatically. To raise the cap, upgrade tier

Tier-gate errors (402, code -32004)

data.type is tier_required, retryable is false, and action is the billing URL — so an agent should upgrade or pick a different tool rather than retry.

MessageCauseFix
Tool 'generate_doodle_vsl' requires 'agency' tier or higher.Your subscription tier is below what the tool requiresUpgrade to the required tier or switch to a tool your tier supports

Tier matrix (current):

Tier requiredTools
Starter (default)All free tools + ad_image, ad_copy, image_variations, carousel, messaging_angles, scrape_offer, pull_reviews, analyze_ad_image, audience_research, decide_creative_strategy, broll_video
ProAll Starter tools + video_reel, vsl_script, email_campaign, find_winning_ads, add_video_captions
AgencyAll Pro tools + doodle_vsl

Tool dispatch errors

CodeMessageCauseFix
-32601Method not found: XMethod name typo (most common: typo in tools/call)Use exactly tools/list, tools/call, initialize, or notifications/initialized
-32601Unknown tool: X. Available tools: ... (HTTP 404, data.type = unknown_tool)Tool name typo or tool not registered. Note: the list shows the advertised tools; some legacy tools (e.g. generate_ad_copy) still work via tools/call even though they're no longer listed — prefer generate_copy.List available tools via tools/list
-32603Missing tool nameparams.name was empty or not a stringPass a non-empty name string in params

Tool-side errors (passed through from underlying edge functions)

When a wrapped tool reaches the actual generation pipeline and that pipeline errors, the failure is mapped to a structured, recoverable code so your agent knows how to react: 402 insufficient credits (-32005) or tier (-32004); 429/5xx upstream (-32010, retryable: true — safe to retry); other 4xx invalid input (-32011, fix the args). Common patterns:

ToolCommon errorCauseFix
generate_ad_copyAnthropic API key required for ClaudeLOCAL dev environment without ANTHROPIC_API_KEYProduction has this set; only seen in local-dev usage
generate_doodle_vslMissing required fields: script, voiceId, userIdMissing script in argsPass script as a string. userId is auto-injected by the MCP server.
generate_broll_videoMissing required fields: script, voiceIdMissing scriptRequired field; voiceId defaults to Brian if omitted
Any async toolJob not found or not owned by this user (in check_generation_status)jobId/jobType mismatch, or job belongs to a different userRe-check the jobId returned by the original async call
Any paid toolInsufficient credits.Org credit balance below tool costTop up credits at Billing

Strategist-specific errors

MessageCauseFix
ANTHROPIC_API_KEY not configured on this environmentProduction env var missing (rare — should always be set on prod)Contact support
Strategist returned invalid JSON. Raw output: ...Anthropic returned non-JSON despite the strict promptRetry the call once; if persistent, file a bug
Strategist response missing manifest arraySchema validation rejected the LLM's outputSame as above — usually a one-off Claude oddity, retry

Claude Code connection issues

SymptomFix
/mcp shows ad-command ✗ disconnectedRestart Claude Code. Verify auth header in ~/.claude.json. Check the Bearer token has no whitespace or newlines around it.
Server health works (curl https://...mcp-server → 200) but Claude Code can't connectSome Claude Code versions cache MCP server lists at session start. A full restart (not just slash-command refresh) is required after config changes.
Tools list is emptyOld client version cached the list before tools were registered. Restart Claude Code.

Network / infrastructure

SymptomCauseFix
connect: timeoutOutbound port 5432 (Postgres direct) blocked on cellular networksSwitch to a wifi network for any psql / Supabase CLI commands. The MCP server itself uses HTTPS (port 443) and works on any network.
503 Service UnavailableEdge function cold start exceeded the thresholdRetry after 1-2 seconds

Where to dig deeper

  • Claude Code logs: ~/.claude/logs/ (or your platform equivalent)
  • Supabase function logs: Dashboard → Functions → mcp-server → Logs
  • Audit trail: every authenticated request writes to mcp_audit_logs. If you self-host or have admin SQL access:
sql
-- Recent failures
SELECT created_at, tool_name, status, error_message, duration_ms
FROM mcp_audit_logs
WHERE status != 'ok' AND created_at > now() - interval '1 hour'
ORDER BY created_at DESC
LIMIT 20;

If something's still confusing, open an issue or email support.

Ad Command — built on the Model Context Protocol