Skip to content

MCP errors

Every code the MCP server can answer with: what the agent reads, why it happened, and what to do next.

In this guide

How an error reaches your agent

A tool result. A tool that can't do what was asked returns a result marked isError with two text blocks: one sentence (what went wrong and what to do), then a JSON object with code, reason, message, fix, doc_url (a link to this page), and, when they apply, details, retry_after_secs and reference.

An HTTP answer before any tool runs. A token that isn't valid gets a 401 that makes the client ask you to sign in again. A closed, suspended or deleted account, a revoked app, an authenticator added after connecting, an outage on our side and too many rejected tokens from one address get a 403, 503 or 429 whose body carries the same JSON object.

A fault on our side carries a reference. Send it to support with roughly when it happened: it finds the server log line with the real cause. Setup and sign-in problems are covered under If something goes wrong.

An argument isn't valid

#validation_error

Why: An argument failed the tool's schema or a limit the app enforces: a field too long, a value the tool doesn't accept, too many images, or a file past the size limits. Nothing was written.

What the agent reads: Some of the arguments aren't valid.

What to do: Correct the fields named in details and call again; get_publishing_rules lists every limit.

upload_files

#validation_error:upload_files

What the agent reads: begin_upload needs at least one file, and every file needs a valid name, content type and size.

What to do: Pass files: [{ name, content_type, bytes }] for each file; details.issues names every problem, and no session was created.

The JSON block also carries issues.

upload_kind

#validation_error:upload_kind

What the agent reads: This server doesn't accept skill files yet; they arrive with release 2.

What to do: Stage images with kind "image"; publish skills from the dashboard until then.

The JSON block also carries kind, accepted_kinds.

upload_session

#validation_error:upload_session

What the agent reads: That upload_session doesn't exist for this account, or it has been cleaned up.

What to do: Call begin_upload, upload each file with its curl line, then pass { upload_session, name }.

The JSON block also carries upload_session.

staged_name

#validation_error:staged_name

What the agent reads: That name isn't one of this upload session's files.

What to do: Use exactly a name you passed to begin_upload for this session.

The JSON block also carries upload_session, name.

staged_missing

can succeed on retry

#validation_error:staged_missing

What the agent reads: That file hasn't been uploaded yet.

What to do: Run its curl line from begin_upload (each URL is valid for 2 hours), then call again.

The JSON block also carries upload_session, name.

staged_kind

#validation_error:staged_kind

What the agent reads: That upload session holds skill files, not images.

What to do: Stage images with begin_upload { kind: "image" } and pass that session instead.

The JSON block also carries upload_session.

staged_too_large

#validation_error:staged_too_large

What the agent reads: That staged file is larger than this upload accepts.

What to do: Start a new begin_upload session and upload a file under details.limit_bytes.

The JSON block also carries limit_bytes.

images

#validation_error:images

What the agent reads: Some images can't be saved.

What to do: Each entry in details.image_errors names the image by its index in images and says what to fix; correct those and call again.

The JSON block also carries image_errors.

too_many_images

#validation_error:too_many_images

What the agent reads: Too many images for this item.

What to do: Send at most details.max images; get_publishing_rules lists the cap per entity.

The JSON block also carries max.

image_type_mismatch

#validation_error:image_type_mismatch

What the agent reads: The image's bytes don't match its content_type.

What to do: Set content_type to the image's real type (PNG, JPEG, WebP or GIF), or convert the file.

image_unknown_type

#validation_error:image_unknown_type

What the agent reads: That file isn't a PNG, JPEG, WebP or GIF image.

What to do: Convert it to PNG, JPEG, WebP or GIF and send it again.

image_decode

#validation_error:image_decode

What the agent reads: That image couldn't be decoded.

What to do: Re-export it as a standard PNG or JPEG and send it again.

image_too_large

#validation_error:image_too_large

What the agent reads: That image is too large to store, even after re-encoding.

What to do: Send a smaller image; a GIF is stored as it is and must be under 2 MB.

image_path

#validation_error:image_path

What the agent reads: That path isn't one of this item's images.

What to do: To keep an image, pass a path from images in the latest read or write response; to add one, stage it or send it inline.

inline_data_uri

#validation_error:inline_data_uri

What the agent reads: data_base64 must be the bare base64, without a data: prefix.

What to do: Send only the part after the comma: iVBORw0KGgo… rather than data:image/png;base64,iVBORw0KGgo….

inline_base64

#validation_error:inline_base64

What the agent reads: data_base64 isn't valid base64.

What to do: Send standard base64 of the image bytes (A to Z, a to z, 0 to 9, + and /, with = padding).

inline_too_large

#validation_error:inline_too_large

What the agent reads: An inline image can be at most 256 KB decoded (about 350,000 characters of base64).

What to do: Stage anything larger, and anything from disk, with begin_upload and pass { upload_session, name }.

The JSON block also carries limit_bytes.

inline_budget

#validation_error:inline_budget

What the agent reads: One call can carry at most 3 MB of inline data across images and files.

What to do: Stage the larger images with begin_upload and pass { upload_session, name } instead.

The JSON block also carries limit_bytes.

images_token_required

#validation_error:images_token_required

What the agent reads: This item already has images, so changing them needs its images_token.

What to do: Send the update again with details.images_token (the set it covers is details.images), or read the item first.

The JSON block also carries images, images_token.

images_token_malformed

#validation_error:images_token_malformed

What the agent reads: images_token isn't a token this server issued.

What to do: Pass the images_token from the latest read or write response unchanged.

images_after_create

#validation_error:images_after_create

What the agent reads: The draft was created, but its images weren't saved.

What to do: Retry the images alone with the update tool on details.created_id; details.image_errors says what to fix. Never create the item again.

The JSON block also carries created_id, image_errors.

prompt_category

#validation_error:prompt_category

What the agent reads: That category doesn't exist.

What to do: Pass a slug from list_categories, or leave category out.

The JSON block also carries category.

prompt_variables

#validation_error:prompt_variables

What the agent reads: The body's {{variables}} can't all be recorded: too many, or one name is too long.

What to do: Keep to the limits get_publishing_rules lists for variables, or pass variables explicitly with the body.

prompt_variables_without_body

#validation_error:prompt_variables_without_body

What the agent reads: variables change only together with the body: one version holds both.

What to do: Send body with variables, or send body alone and the variables are read from its {{names}}.

prompt_update_empty

#validation_error:prompt_update_empty

What the agent reads: update_prompt was called with nothing to change.

What to do: Send at least one field to change; every field you leave out keeps its value.

skill_package

#validation_error:skill_package

What the agent reads: The skill package isn't valid.

What to do: Fix every entry in details.issues (each names a path and a reason) and send the package again; get_publishing_rules lists the live limits.

The JSON block also carries issues.

skill_inline_file

#validation_error:skill_inline_file

What the agent reads: An inline skill file needs exactly one of content or content_base64.

What to do: Send text as content and a binary file, such as an image, as bare base64 in content_base64.

The JSON block also carries path.

skill_inline_budget

#validation_error:skill_inline_budget

What the agent reads: An inline skill package can carry at most 3 MB of decoded content in one call, images included.

What to do: Stage the files with begin_upload { kind: "skill_file" }, run the curl lines, and pass { kind: "staged", upload_session } instead.

The JSON block also carries limit_bytes.

skill_inline_time

#validation_error:skill_inline_time

What the agent reads: This inline package has too many files to stage within one call.

What to do: Stage the files with begin_upload { kind: "skill_file" }, run the curl lines, and pass { kind: "staged", upload_session } instead.

The JSON block also carries max_files.

skill_github_source

#validation_error:skill_github_source

What the agent reads: The GitHub source isn't valid.

What to do: Pass url as https://github.com/owner/repo, ref as a branch, tag or commit, and subdir as a folder path inside the repository.

The JSON block also carries fieldErrors.

skill_session_kind

#validation_error:skill_session_kind

What the agent reads: That upload session holds images, not skill files.

What to do: Stage skill files with begin_upload { kind: "skill_file" } and pass that session as the source.

The JSON block also carries upload_session.

skill_staged_missing

can succeed on retry

#validation_error:skill_staged_missing

What the agent reads: Some files of that upload session were never uploaded.

What to do: Run the curl line of each file in details.missing (each URL works for 2 hours), then call again with the same session.

The JSON block also carries upload_session, missing.

skill_staged_changed

#validation_error:skill_staged_changed

What the agent reads: Files in that upload session changed after the dry run.

What to do: Run the dry run again to see the files as they are now, or upload what you meant, then call again.

The JSON block also carries upload_session, changed.

skill_no_version

#validation_error:skill_no_version

What the agent reads: The skill has no files registered yet, so it can't be submitted.

What to do: Register a package first with update_skill and a source, then call publish_skill.

skill_install_target

#validation_error:skill_install_target

What the agent reads: Name the skill to install with exactly one of skill_id or ref.

What to do: Pass skill_id (from search results or a public page) or ref as handle/slug, not both.

skill_cursor

#validation_error:skill_cursor

What the agent reads: That cursor isn't one this server issued.

What to do: Pass the next_cursor from the previous list_my_skills response unchanged, or omit cursor to start from the newest.

blog_status_published

#validation_error:blog_status_published

What the agent reads: An app can't publish a blog post: status takes draft or unlisted here.

What to do: Save it as draft, or as unlisted to share it by link, then publish it with one click from My Blogs in the dashboard (/dashboard/blog/mine).

The JSON block also carries fieldErrors.

prompt_not_linkable

#validation_error:prompt_not_linkable

What the agent reads: You can only link one of your own prompts.

What to do: list_my_prompts lists them: pass one of their ids as prompt_id, omit the field, or send null to unlink.

The JSON block also carries fieldErrors.

skill_not_linkable

#validation_error:skill_not_linkable

What the agent reads: You can only link a skill you own.

What to do: list_my_skills lists them: pass one of their ids as skill_id, omit the field, or send null to unlink.

The JSON block also carries fieldErrors.

challenge_not_linkable

#validation_error:challenge_not_linkable

What the agent reads: You can only link a challenge you posted or submitted a solution to, and only while it is still live.

What to do: Pass the id of such a challenge as request_id, omit the field, or send null to unlink.

The JSON block also carries fieldErrors.

staged_over_declared

#validation_error:staged_over_declared

What the agent reads: That staged file is larger than the size begin_upload declared for it.

What to do: Call begin_upload again with each file's exact size on disk in bytes, run the new curl lines, and pass the new upload_session.

The JSON block also carries upload_session, name, declared_bytes, bytes.

Not found

#not_found

Why: The id names nothing this account can see. It was deleted, it was mistyped, or it belongs to another member and isn't public. The tools with my in their name reach only your own items.

What the agent reads: We couldn't find that.

What to do: list_my_prompts shows what you can edit; reference another member's prompt by its URL from search_prompts.

prompt_replay_gone

#not_found:prompt_replay_gone

What the agent reads: The prompt this idempotency_key created no longer exists: it was deleted since.

What to do: Call create_prompt again with a NEW idempotency_key to create it again; list_my_prompts shows what exists.

The JSON block also carries original_outcome.

reveal

#not_found:reveal

What the agent reads: That prompt can't be revealed: it doesn't exist, or it isn't published and public.

What to do: search_prompts finds the public prompts you can reveal; for one of your own, use get_my_prompt.

skill

#not_found:skill

What the agent reads: We couldn't find that skill.

What to do: list_my_skills shows the skills you can edit; install another member's published skill with install_skill.

skill_unavailable

#not_found:skill_unavailable

What the agent reads: That skill isn't available to install.

What to do: Pass the skill_id or the handle/slug from the skill's public page; only published, public skills and your own can be installed.

skill_install_ticket

#not_found:skill_install_ticket

What the agent reads: There's no install of that skill to confirm.

What to do: Call install_skill first, write and verify the files, then call confirm_skill_install with the same skill_id.

skill_create_incomplete

#not_found:skill_create_incomplete

What the agent reads: The skill this idempotency_key created no longer exists: it was deleted since.

What to do: Call create_skill again with a NEW idempotency_key to create it again; list_my_skills shows what exists.

The JSON block also carries original_outcome.

blog_post

#not_found:blog_post

What the agent reads: We couldn't find that blog post.

What to do: list_my_blog_posts lists the posts this account can read and edit.

Another member's item

#not_owner

Why: The item exists, but another member owns it. An app acts as you, so it can change only what you own.

What the agent reads: That item belongs to another member.

What to do: list_my_prompts shows what you can edit; reference another member's prompt by its URL.

skill

#not_owner:skill

What the agent reads: That skill belongs to another member.

What to do: list_my_skills shows the skills you can edit; install another member's published skill with install_skill.

blog_post

#not_owner:blog_post

What the agent reads: That blog post belongs to another member.

What to do: list_my_blog_posts lists this account's own posts: an app reads and edits only those, and admins moderate from the dashboard.

The connection can't submit

#insufficient_scope

Why: When you approved the app you chose Create and edit. Submitting for review, a create that submits at once, and an update that sends a published item's change to review need Create, edit and submit.

What the agent reads: This app's connection can create and edit but not submit for review.

What to do: In Settings → Account → Connected apps, choose "Change what it can do" for this app and pick Create, edit and submit. Open the setting.

The JSON block also carries settings_url.

The plan doesn't include it

#insufficient_tier

Why: The account's plan doesn't cover what the call asked for, such as reading a premium prompt.

What the agent reads: This account's plan can't do that.

What to do: Compare plans at /pricing; the dashboard shows what the current plan includes.

The JSON block also carries current, required.

premium_view

#insufficient_tier:premium_view

What the agent reads: That prompt is premium, and this account's plan doesn't include premium prompts.

What to do: Upgrade at /pricing (Explorer or above), then reveal it again; free prompts need no plan.

The JSON block also carries feature, current, required.

premium_skill

#insufficient_tier:premium_skill

What the agent reads: That skill is premium, and this account's plan doesn't include premium skills.

What to do: Upgrade at /pricing (Explorer or above), then install it again; free skills need no plan.

The JSON block also carries feature, current, required.

The account is closing

#account_closing

Why: The account is winding down, so calls that take on something new, such as submitting for review, are refused until the wind-down is cancelled. Reads, drafts and edits still work.

What the agent reads: This account is closing, so it can't take on anything new.

What to do: Keep the account from Settings → Account first; drafts, edits and reads still work meanwhile. Open the setting.

The JSON block also carries settings_url.

The account is closed

#account_disabled · also HTTP 403 before any tool runs

Why: The account was closed from Settings or disabled by an admin, so the app's token no longer acts for anyone.

What the agent reads: This account is closed.

What to do: Reactivate it at /account/recover, then connect this app again.

The JSON block also carries recovery_url.

The account is suspended

#account_suspended · also HTTP 403 before any tool runs

Why: An admin suspended the account. Every call is refused while the suspension lasts.

What the agent reads: This account is suspended.

What to do: Email support if you think that's wrong.

The account no longer exists

#account_gone · also HTTP 403 before any tool runs

Why: The account behind the token was deleted for good, so there is nobody left for the app to act as.

What the agent reads: This account no longer exists.

What to do: Sign up again at the site, then connect this app to the new account.

The app was revoked

#grant_revoked · also HTTP 403 before any tool runs

Why: Someone revoked this app in Settings → Account → Connected apps. The revocation takes effect at once.

What the agent reads: This app's connection was revoked.

What to do: Connect again from the app; you'll be asked to approve it. Open the setting.

The JSON block also carries settings_url.

An authenticator was added after connecting

#mfa_required · also HTTP 403 before any tool runs

Why: The account added an authenticator after this app connected, so the app's token was issued without the second factor and every call it makes is refused, reads included.

What the agent reads: This account added an authenticator after the app was connected.

What to do: Revoke this app in Settings → Account → Connected apps and connect again; you'll be asked for your authenticator code. Open the setting.

The JSON block also carries settings_url.

The token isn't valid

#invalid_token · also HTTP 401 before any tool runs

Why: The token expired, was issued for something else, or isn't an app's token at all (a browser session can't be used here). Expiry is normal: clients refresh the token on their own and ask you to sign in again only when the refresh fails.

What the agent reads: The token isn't valid, or has expired.

What to do: Re-authenticate: run /mcp in Claude Code, or codex mcp login promptdock in Codex.

A limit was reached

can succeed on retry

#rate_limited · also HTTP 429 before any tool runs

Why: A limit was reached: the calls each member may make per minute, a tool's own budget, the 20 prompt reveals or the 5 new prompts (drafts included) an app may make for a member in any hour, the submission budget, the daily premium-reveal limit, or, before any tool runs, the per-address limit on rejected tokens. A call the hourly limits refuse takes nothing from them.

What the agent reads: Too many calls right now.

What to do: Wait retry_after_secs seconds and call again.

The JSON block also carries retry_after_secs.

member

can succeed on retry

#rate_limited:member

What the agent reads: Too many calls in the last minute (the limit is 240 a minute per member).

What to do: Wait retry_after_secs seconds and call again; batch reads where you can.

The JSON block also carries retry_after_secs, scope.

tool

can succeed on retry

#rate_limited:tool

What the agent reads: This tool's own limit was reached.

What to do: Wait retry_after_secs seconds and call again; the limit is per tool, so other tools still work.

The JSON block also carries retry_after_secs, scope.

publish

can succeed on retry

#rate_limited:publish

What the agent reads: Submissions are limited to 5 an hour and 20 in any 24 hours because a person reviews each one.

What to do: Submit again after the wait, or from the dashboard.

The JSON block also carries retry_after_secs, scope.

daily_premium_cap

can succeed on retry

#rate_limited:daily_premium_cap

What the agent reads: You've hit the premium reveal limit for the day.

What to do: Try again after retry_after_secs seconds; free prompts stay available meanwhile.

The JSON block also carries retry_after_secs, scope.

reveals

can succeed on retry

#rate_limited:reveals

What the agent reads: Prompt reveals from connected apps are limited to 20 an hour per member.

What to do: Reveal again after retry_after_secs seconds, or open the prompt in the dashboard. Prompts you already revealed in this conversation don't need revealing again.

The JSON block also carries retry_after_secs, scope.

prompt_creates

can succeed on retry

#rate_limited:prompt_creates

What the agent reads: New prompts from connected apps are limited to 5 an hour per member. Nothing was created.

What to do: Create it again after retry_after_secs seconds with the same idempotency_key, or create it in the dashboard. Editing an existing prompt isn't limited by this.

The JSON block also carries retry_after_secs, scope.

upload_sessions

can succeed on retry

#rate_limited:upload_sessions

What the agent reads: Too many open upload sessions (at most 5 per member).

What to do: Use an open session in a create or update, or wait retry_after_secs seconds for the oldest one to expire.

The JSON block also carries retry_after_secs, scope.

upload_bytes

can succeed on retry

#rate_limited:upload_bytes

What the agent reads: Open upload sessions may reserve at most 50 MB per member, and this one would pass it.

What to do: Use an open session first, stage fewer files per call, or wait retry_after_secs seconds for the oldest one to expire.

The JSON block also carries retry_after_secs, scope.

daily_premium_skill_cap

can succeed on retry

#rate_limited:daily_premium_skill_cap

What the agent reads: You've reached the daily limit on premium skill installs.

What to do: Install again after retry_after_secs seconds; free skills, and premium skills you already installed, stay available.

The JSON block also carries retry_after_secs, scope.

github_import

can succeed on retry

#rate_limited:github_import

What the agent reads: GitHub's rate limit was reached, so the repository couldn't be read.

What to do: Try again later, or stage the files with begin_upload { kind: "skill_file" } and pass { kind: "staged", upload_session }.

The JSON block also carries scope.

The state changed

can succeed on retry

#conflict

Why: The item changed between your read and your write, or an idempotency_key is still in use or belongs to another tool. An item's state can block an app too, however fresh its read: a moderator removed it, or it is a published blog post, which only the dashboard changes.

What the agent reads: That conflicts with the current state.

What to do: Read the item again and retry with its current values.

images_changed

can succeed on retry

#conflict:images_changed

What the agent reads: The images changed since you read them.

What to do: Use the images and images_token in details and send the update again.

The JSON block also carries images, images_token.

idempotency_in_flight

can succeed on retry

#conflict:idempotency_in_flight

What the agent reads: A create with this idempotency_key is still running.

What to do: Wait retry_after_secs seconds and call again with the SAME key; never a new one.

The JSON block also carries retry_after_secs.

idempotency_cross_tool

#conflict:idempotency_cross_tool

What the agent reads: This idempotency_key was used by another tool.

What to do: Use a new key; a key belongs to one create.

The JSON block also carries tool.

version_conflict

can succeed on retry

#conflict:version_conflict

What the agent reads: This item was edited since you read it.

What to do: Read it again (get_my_prompt) and resend your change against the current version.

version_conflict

can succeed on retry

#version_conflict

What the agent reads: This item was edited since you read it.

What to do: Read it again (get_my_prompt) and resend your change against the current version.

skill_slug_taken

#conflict:skill_slug_taken

What the agent reads: You already have a skill with that slug.

What to do: Pick another slug, or omit slug to derive one from the title.

version_conflict:skill_install

can succeed on retry

#version_conflict:skill_install

What the agent reads: A new version of that skill was approved after you named its version.

What to do: Call install_skill again without version_id (or with details.current_version_id) and verify the files it returns.

The JSON block also carries current_version_id.

removed_by_moderator

#conflict:removed_by_moderator

What the agent reads: A moderator removed this post, so it can't be changed while it's removed.

What to do: Open it in My Blogs (/dashboard/blog/mine) to read the reason and request a review; reading it still works.

blog_published

#conflict:blog_published

What the agent reads: This post is published, so an app can't change it.

What to do: Edit or unpublish it from My Blogs in the dashboard (/dashboard/blog/mine). An app edits drafts and unlisted posts only.

Something on our side is unavailable

can succeed on retry

#service_unavailable · also HTTP 503 before any tool runs

Why: A part of Prompt Dock the call needed (the database or the sign-in server) didn't answer for a moment.

What the agent reads: It's not you, it's us. We're working on it.

What to do: Retry in a few seconds; if you were creating something, reuse the same idempotency_key.

The JSON block also carries reference.

An unexpected fault

can succeed on retry

#internal

Why: Something failed on our side that we didn't expect. The reference ties your report to the server log, where the cause is recorded.

What the agent reads: It's not you, it's us. We're working on it.

What to do: Retry in a few seconds; if you were creating something, reuse the same idempotency_key.

The JSON block also carries reference.

Other codes

Codes the wider Prompt Dock API can name that an MCP tool isn't designed to send. Each is here so that every link an error carries lands somewhere.

No credentials

#unauthenticated

What it says: You must be signed in to do that.

Why: The request carried no token at all. An MCP client always sends one, so this usually means the client lost its sign-in.

What to do: Re-authenticate: run /mcp in Claude Code, or codex mcp login promptdock in Codex.

A recent browser sign-in is needed

#reauth_required

What it says: Sign in again to continue payout setup.

Why: Payout actions need a recent sign-in in the browser, which an app can't provide.

What to do: Do it from the dashboard in your browser.

A create needs a key

#idempotency_key_required

What it says: This request requires an idempotency key.

Why: A route that creates something was called without the idempotency key it requires.

What to do: Send a fresh uuid as the key and reuse it only to retry that same create.

The CLI is out of date

#upgrade_required

What it says: Your promptdock CLI is out of date — upgrade to continue.

Why: This code belongs to the promptdock CLI's version floor; the MCP server never sends it.

What to do: Upgrade the CLI; the CLI's own reference explains every gate. upgrade_required in the CLI reference.