Bỏ qua để đến nội dung

Error code reference

Nội dung này hiện chưa có sẵn bằng ngôn ngữ của bạn.

Errors from the MCP server come in two shapes:

  • HTTP-level: returned with a non-2xx status from /mcp or /admin/api/*. Usually auth-related (401, 403).
  • Tool result: { "content": [...], "isError": true } on tools/call. The text content has the format <code>: <message>. Every tool call also writes an audit_log row with the code in the error column.

The codes below are stable — Claude (and other clients) can switch on them in retry logic.

HTTP 401 Unauthorized. Returned when the bearer or OAuth token can’t be verified.

TriggerFix
Authorization header missingAdd Authorization: Bearer <token>.
OAuth oat_* token expired (default 1h)Let Claude refresh — auto for Custom Connector; manual re-auth otherwise.
OAuth oat_* revokedRe-add the connector in Claude Desktop.
Bearer sn_prod_* not in D1Token was revoked or never existed. Mint a fresh one at /admin/tokens.
Master token used on /mcpThe master token is for /admin/* only. Mint a regular token.

The response also carries WWW-Authenticate: Bearer resource_metadata="…/.well-known/oauth-protected-resource" so MCP clients can autodiscover OAuth.

HTTP 403 Forbidden. The token is valid but doesn’t include the requested site or tool.

TriggerFix
site_id not in tokens.allowed_sites (or owner’s user_sites)/admin/tokens → edit → tick the site. Or for OAuth, grant the site to the user at /admin/users.
Tool name not in tokens.allowed_tools/admin/tokens → edit → tick the tool.

See Tokens & scoping for the full scope-check algorithm.

HTTP 403 Forbidden. A regular-user token tried to call a tool restricted to super-admin (master-token-issued) bearer tokens.

The only tool in this category today is delete_astro_route. See Architecture — hard rule.

Fix: mint the bearer token from the Master token tab of /admin/login instead of a user account. Tokens minted from the master tab have owner_user_id IS NULL which is the runtime gate.

HTTP 403 Forbidden. Admin-side check — usually “super-admin only” for the admin API (e.g. user management).

Fix: log in as super-admin via the master token.

HTTP 403 Forbidden. The adapter refused a payload that would violate the no-publish-now / no-delete rule.

TriggerFix
status=publish on WP post/page create or updateUse schedule_draft / schedule_page with a future ISO8601 time.
Duda POST /publish without schedule_publish_dateSame — schedule, don’t publish-now.
scheduled_at within 60s of nowPick a time ≥ 60s in the future.
DELETE on a WP post or pageThis server doesn’t expose delete tools. Delete in wp-admin.

HTTP 400 Bad Request. Argument missing, wrong type, or fails an enum check.

The message names the offending field — e.g. title is required, scheduled_at must be a valid ISO8601 string, tags must be string[].

Fix: correct the argument shape. Tool input schemas are in /reference/tools/ — Claude usually self-corrects after one round-trip.

HTTP 400 Bad Request. An Astro route doesn’t satisfy validation rules.

Bad routes include:

  • Contains .. (path traversal).
  • Contains [, ], \, ?, #, %.
  • Empty segments (/foo//bar).
  • Segments with leading/trailing dashes, or non-alphanumeric chars.
  • Dynamic-route brackets (/[slug]) — explicit routes only for v1.

Fix: rephrase the route. Allowed format per segment: [a-z0-9][a-z0-9-]*[a-z0-9]? (case-insensitive).

HTTP 400 Bad Request. The create_page_from_code / update_page_from_code validator caught one of:

  • <script src="…"> in HTML — inline JS only.
  • <iframe> in HTML — banned for cache-plugin safety.
  • @import url(https://…) in CSS — bypasses the scope rewriter.

Fix: inline the asset, or host it via the theme <head> and reference by selector. See Code-first pages — validation rules.

HTTP 413 Payload Too Large. Size cap exceeded on one of:

  • html > 200 KB
  • css > 100 KB
  • js > 100 KB

Fix: split the page; lazy-load below-the-fold sections; or move heavy assets out to <link> / <img src> referencing the theme’s media library.

HTTP 400 Bad Request. Elementor template duplicate was called with a variables map that doesn’t cover every {{KEY}} the template references.

The message includes the missing keys: Missing variables: HERO_SUB, CTA_LINK.

Fix: add the missing entries to variables. To see what a template requires, call list_page_templates.

HTTP 400 Bad Request. save_md_to_github received markdown that doesn’t start with a --- YAML frontmatter block.

Fix: prepend the YAML header. Minimum:

---
title: ...
slug: ...
---

See Content + Design teams.

HTTP 400 Bad Request. A tool was called on a site whose platform doesn’t support that operation.

TriggerFix
create_page_from_code on Duda or AstroWordPress only.
duplicate_page on WordPressDuda only.
inject_page_section on WordPressDuda only.
list_taxonomies / create_taxonomy on DudaWordPress only.
Post / page tools on AstroUse the Astro tools instead.
create_page_draft on AstroUse create_astro_route.
diagnose_site on non-WordPressThe diagnostics are WP-specific.

HTTP 400 Bad Request. The WP site has multiple builders enabled, and the caller didn’t specify page_builder.

Fix: pass page_builder: "gutenberg" or "elementor". To discover which builders are enabled, call list_builders_for_site.

HTTP 400 Bad Request. page_builder was set to a builder that isn’t in the site’s available_builders list.

Fix: either pick an available builder, or open /admin/sites → edit and tick the missing builder.

HTTP 400 Bad Request. deploy_md_to_site was asked to render to a target site where Elementor is the only available builder. Markdown can’t generate an Elementor JSON layout.

Fix: either enable Gutenberg on the target site, or call create_page_draft directly with elementor_template_id + variables.

HTTP 500 Internal Server Error. The template’s _elementor_data postmeta isn’t valid JSON.

Fix: open the template in wp-admin → Elementor → save again (re-serializes the JSON). If it persists, the postmeta has likely been hand-edited.

HTTP 409 Conflict. The site has no github_repo configured.

Fix: /admin/sites → edit → set github_repo (format owner/repo).

HTTP 409 Conflict. No GitHub App installation exists for the repo’s owner account.

Fix: /admin/githubInstall on org/user. Pick the account that owns the repo.

HTTP 409 Conflict. update_astro_route / delete_astro_route was called on a .astro file that was NOT created by this server (no marker comment).

The marker is Generated by SEO Navigator MCP in the file’s frontmatter comments. Pass force: true to overwrite/delete a hand-written file anyway.

HTTP 409 Conflict. You passed an sha for optimistic concurrency, but the file’s current sha on the branch is different (concurrent edit).

Fix: re-read the file (list_astro_routes or read_md_from_github) and retry with the fresh sha.

HTTP 409 Conflict. create_astro_route would overwrite an existing file.

Fix: call update_astro_route instead. It refuses non-MCP-managed files by default — pass force: true to overwrite anyway.

HTTP 503 Service Unavailable. check_astro_deploy was called but the worker has no CLOUDFLARE_API_TOKEN + CLOUDFLARE_ACCOUNT_ID secrets.

Fix: super-admin sets them with wrangler secret put. See Deploy — secrets.

The tool normally hides itself from tools/list when the secrets are missing, so this only fires if a client invokes it by name regardless.

HTTP 409 Conflict. The site is an Astro site but has no cf_pages_project set.

Fix: /admin/sites → edit → set cf_pages_project to the slug shown in Cloudflare Pages (e.g. marketing-site).

HTTP 4xx or 5xx mirroring the upstream status (clamped to 400–599). The adapter contacted WP / Duda / GitHub / Cloudflare Pages and got a failure response.

The error message includes the upstream HTTP status and a body excerpt: E_UPSTREAM: WP 400 — Invalid term id: 0.

Common causes:

  • WP 400 invalid term id — usually a tag/category mismatch. The worker auto-resolves names → IDs in deploy_md_to_site and the regular post tools, but if you bypass that path and pass an integer that doesn’t exist, you’ll see this.
  • WP 401 — Application Password wrong or revoked. Re-issue from wp-admin → Users → Profile.
  • WP 403 — App Password user lacks edit_pages / edit_posts. Grant the role in wp-admin.
  • WP 404post_id / page_id doesn’t exist on this site, or it’s a Duda ID being used as a WP ID. Always pair site_id + post_id/page_id.
  • Duda 401DUDA_API_USER/DUDA_API_PASS wrong. The worker uses a single shared credential pair across all Duda sites.
  • Duda 404 site_aliasduda_site_name doesn’t match the Duda site’s alias. Open the Duda dashboard while editing the site; the URL contains the alias (e.g. 7a1c9e2f).
  • GitHub 401 — the cached installation token expired or the GitHub App was uninstalled. Visit /admin/github to reinstall.
  • GitHub 422 path is too long — GitHub limits paths to 250 chars. Move to a shallower folder.
  • Cloudflare 1xxx error — usually a transient origin firewall block. Retry; if persistent, the site’s WAF is rejecting the worker’s request.

HTTP 500 Internal Server Error. Something inside the worker hit an “impossible” branch (typically a credential kind mismatch — Duda creds appearing where the code expected WP creds).

Fix: this should never happen at runtime. If you see it, file an issue on GitHub with the audit row.

HTTP 404 Not Found. Looked up a record that doesn’t exist.

TriggerFix
site_id not in D1 sites table/admin/sites → add it, or check the slug.
read_md_from_github path doesn’t existRun list_md_from_github to see what’s there.
update_astro_route / delete_astro_route on a route that doesn’t existUse create_astro_route instead.
deploy_md_to_site source file missingSame as read_md_from_github.

Tool denied (not a code, but worth knowing)

Section titled “Tool denied (not a code, but worth knowing)”

When the token’s allowed_tools doesn’t include a tool, the worker returns a JSON-RPC tool result { isError: true, content: "Tool 'X' not allowed for this token" } with audit status=denied. This is the same shape as E_SCOPE_DENIED from the user’s perspective — fix is identical: edit token scope.

Proxy tools matching the destructive guardrail ((delete|remove|trash|destroy)(page|post|template|content|media) or publish-* except unpublish-*) are filtered out of tools/list and refused at tools/call, regardless of the token’s allowed_tools. There’s no way to enable these — see Architecture — hard rule.

  1. Open /admin/audit. Filter by status=error and the time range. Each row has the full args and error string.
  2. Cross-reference tool + error against the table above.
  3. For upstream errors, the message includes the body excerpt — useful when WP returns a custom JSON shape (e.g. WAF blocking a specific header).
  4. For repeated E_AUTH, check tokens.revoked_at in D1 (wrangler d1 execute blog_mcp --remote --command "SELECT id, name, revoked_at FROM tokens").

For anything not covered here, the source of truth is src/utils/errors.ts

  • grep -r "new AppError" src/ in the code repo.