Update an existing app
Storage survives updates. Existing contracts retain synchronous PUT and optional If-Match. ESM saves require Idempotency-Key and If-Match carrying the current desired source revision; accepted source advances desired while active remains the last working build. Omitting ui/styles preserves desired values only for ESM; null clears. Successful builds publish automatically; later saves supersede pending builds.
/app/{id}AuthorizationBearer token (chrm_app_*) · headerrequiredPer-app token returned once by POST /app for anonymous creates. Authorises mutations and /api/* calls on that one app only.
AuthorizationBearer token (chrm_user_*) · headerrequiredUser-scoped personal access token. Mint via POST /api/token after signing in, or via the device-pairing flow at POST /api/pair/start. Accepted by every operation that lists userToken in its security; operations that list only sessionCookie refuse it with 401 unauthorized.
idstringrequiredIdempotency-KeystringRequired for ESM saves. Reuse the same key, body, target and If-Match after response loss; a changed request with that key returns idempotency_conflict. Use a fresh key for each intentional save.
If-MatchstringValidator "<N>" for revision N from desired GET /app/:id/source. Required for ESM saves and migrations; optional for existing-contract PUT. The weak form W/"<N>" is also accepted so clients can return the response ETag verbatim.
application/jsonmodulestringrequiredReplacement server ES module source. Must export a literal canonical manifest and a routes array. A route handler returns exactly the value declared by outputSchema; for outputSchema: { type: "array", items: ... }, return the array directly. Charming adds the HTTP transport envelope, so do not add { ok, value } or { value } unless those fields belong to outputSchema itself. default.fetch is an optional unmatched-request fallback; when absent, Charming supplies a generic 404 handler. Keep the stored contract’s exact schema. ESM source is statically checked and built after acceptance.
uistring | nullESM browser module: omit to preserve desired UI, pass null to clear. Existing-contract PUT retains replacement semantics.
stylesstring | nullESM: omit to preserve desired styles, pass null to clear.
descriptionstring | nullOmit to preserve the desired description; pass null to clear.
migrate_contractbooleanRequired as true when changing a stored contract. ESM migration requires the explicit ESM schema, Idempotency-Key and desired-source If-Match; it publishes only after a successful build. Source submissions do not roll back contracts. History can explicitly restore a retained validated existing-contract revision.
Updated
idstring<uuid>requiredmanifestIdstringrequireddisplayNamestringrequireddescriptionstring | nullurlstring<uri>requiredcapabilitiescapabilitiesrequiredShow propertiesHide properties
capabilitiesiconIcon | nullShow propertiesHide properties
emojistringrequiredA single emoji, rendered centered (e.g. ⚽). Extra glyphs are dropped.
bgstringrequiredBackground color as a hex string (#rgb, #rrggbb, or #rrggbbaa). Named colors ("green"), rgb()/hsl(), and image URLs are rejected.
nullclaimedbooleanrequiredrevisionRevisionrequiredServer-owned app source revision. New apps start at 1, each successful source write advances it once, and historical null counters project as 0. If-Match: "<N>" and expected_revision carry this revision through its canonical concurrency grammar.
warningsstring[]Non-blocking publish feedback (#1126), present only when static validation found UI/backend contract mismatches. The write succeeded.
ESM source accepted for a background build. This response does not mean the app has published. Poll statusUrl until a terminal state; new creation has no runnable app or URL until published.
okbooleanrequiredtruebuildIdstringrequiredintentstringrequiredcreateupdatemigraterestorecopystatestringrequiredqueuedresolvingbuildingvalidatingpublishedfailedsupersededcanceledexpiredsourceEtagstringrequiredstatusUrlstring<uri>requiredretryAfterSecondsintegerappIdstring<uuid>revisionintegerPublished app source revision. Present only after successful publication.
desiredRevisionintegeractiveRevisionintegerurlstring<uri>attemptsintegerrequiredacceptedAtstring<date-time>requiredupdatedAtstring<date-time>requiredfinishedAtstring<date-time> | nullrequiredelapsedMsintegerrequiredlockStatestringrequiredlockedunresolvedinputDigeststringrequiredlockDigeststringresolvedDependenciesobjectShow propertiesHide properties
serverobjectrequiredclientobjectrequiredqueueDeadlinestring<date-time>requireddeadlinestring<date-time>requiredinspectionExpiresAtstring<date-time> | nullrequiredidempotencyExpiresAtstring<date-time> | nullrequiredsourceobjectShow propertiesHide properties
modulestringrequireduistring | nullrequiredstylesstring | nullrequireddescriptionstring | nullrequirederrorobjectShow propertiesHide properties
kindstringrequiredmessagestringrequiredretryablebooleanrequireddetailsobjectShow propertiesHide properties
executionstringrequirednot_startedmay_have_runoperationIdstringrequiredreservationIdstringexecutionstringrequiredmay_have_runtargetstringspecifierstringlineintegercolumnintegerInvalid module/ui/styles, unexpected body keys, or malformed If-Match.
okbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
not_foundunknown_operationoperation_not_foundmethod_not_allowedoperation_failedapp_busyvisitor_rate_limitedservice_busyunauthorizedsign_in_requiredtoken_expiredforbiddenaccount_not_joinedforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiunpinned_cdn_scriptinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takeninvalid_domaindomain_takendomain_existsdomain_provider_unavailableapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinewebhook_limit_exceededduplicate_webhookwebhook_disabledversion_limit_exceededplan_requiredstorage_limit_exceededcopy_data_forbiddencopy_data_too_largemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. token_revoked_post_claim is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the recovery field on the same error object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimplanstringPresent on every plan refusal: the tier the caller was refused under. Its presence is what marks an error as a plan refusal rather than a validation or permission failure.
freeprobusinessenterpriselimitstring | integerWhich ceiling the call met, keyed by kind. A plan refusal (*_limit_exceeded) names the countable that ran out — version_history, routines_per_app, routines_per_owner, webhooks_per_app, webhooks_per_owner — and pairs it with max. An app_busy refusal names the bound it met and pairs it with observed and allowed; no plan lifts any of them. Two are per-app run bounds, concurrent_runs and runs_per_window; the third, render_token_refresh, is the page render asking for a new render-token secret, held by 10 per app per client IP and 60 per app across every address in a 60 second window, and observed/allowed name whichever of those two refused. An edits_too_large rejection carries the numeric cap that was exceeded instead of a name.
rungstringOn an app_busy refusal, how hard the app's own refusal ladder is refusing: throttled is the plain ceiling breach above; parked means a caller kept calling inside a wait it was given, so the server mints its own Retry-After (doubling from 60s to a 300s cap) and refuses until a quiet window passes even once the ceiling clears; closed is the same, plus the response closes the connection. Absent on every other kind.
throttledparkedclosedmaxintegerOn a *_limit_exceeded refusal, that limit's number on the caller's plan.
featurestringOn a plan_required refusal, the capability the plan does not include. Never paired with limit / max.
custom_domainwatermark_removalteamsupgradeUrlstring<uri>Absolute link to the owner's own billing page, where the refusal is lifted — the team's page for a team-owned app. Omitted only when the owner has no handle and therefore no settings page of their own, so treat it as optional and fall back to your own copy. MCP appends it as an Upgrade: <url> last line; the CLI prints it under the message.
recoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on kind. Attached to error envelopes the agent can self-correct on: pair for token_revoked_post_claim 401s (#1284), retry for 429s, shrink for too-large / quota-exceeded 413s, refetch for 412 revision_mismatch / invalid_if_match / 428 precondition_required, fix_route_label for 403 forbidden_write, rename for 409 manifest_id_immutable / manifest_id_conflict, and migrate_contract for 422 contract_migration_required. Every instructions string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the RateLimit-Reset and Retry-After headers on the same response.
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredWhich input tripped the cap.
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
kindstringrequiredrenameinstructionsstringrequiredkindstringrequiredmigrate_contractinstructionsstringrequiredToken mismatch or wrong scope.
okbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
not_foundunknown_operationoperation_not_foundmethod_not_allowedoperation_failedapp_busyvisitor_rate_limitedservice_busyunauthorizedsign_in_requiredtoken_expiredforbiddenaccount_not_joinedforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiunpinned_cdn_scriptinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takeninvalid_domaindomain_takendomain_existsdomain_provider_unavailableapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinewebhook_limit_exceededduplicate_webhookwebhook_disabledversion_limit_exceededplan_requiredstorage_limit_exceededcopy_data_forbiddencopy_data_too_largemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. token_revoked_post_claim is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the recovery field on the same error object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimplanstringPresent on every plan refusal: the tier the caller was refused under. Its presence is what marks an error as a plan refusal rather than a validation or permission failure.
freeprobusinessenterpriselimitstring | integerWhich ceiling the call met, keyed by kind. A plan refusal (*_limit_exceeded) names the countable that ran out — version_history, routines_per_app, routines_per_owner, webhooks_per_app, webhooks_per_owner — and pairs it with max. An app_busy refusal names the bound it met and pairs it with observed and allowed; no plan lifts any of them. Two are per-app run bounds, concurrent_runs and runs_per_window; the third, render_token_refresh, is the page render asking for a new render-token secret, held by 10 per app per client IP and 60 per app across every address in a 60 second window, and observed/allowed name whichever of those two refused. An edits_too_large rejection carries the numeric cap that was exceeded instead of a name.
rungstringOn an app_busy refusal, how hard the app's own refusal ladder is refusing: throttled is the plain ceiling breach above; parked means a caller kept calling inside a wait it was given, so the server mints its own Retry-After (doubling from 60s to a 300s cap) and refuses until a quiet window passes even once the ceiling clears; closed is the same, plus the response closes the connection. Absent on every other kind.
throttledparkedclosedmaxintegerOn a *_limit_exceeded refusal, that limit's number on the caller's plan.
featurestringOn a plan_required refusal, the capability the plan does not include. Never paired with limit / max.
custom_domainwatermark_removalteamsupgradeUrlstring<uri>Absolute link to the owner's own billing page, where the refusal is lifted — the team's page for a team-owned app. Omitted only when the owner has no handle and therefore no settings page of their own, so treat it as optional and fall back to your own copy. MCP appends it as an Upgrade: <url> last line; the CLI prints it under the message.
recoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on kind. Attached to error envelopes the agent can self-correct on: pair for token_revoked_post_claim 401s (#1284), retry for 429s, shrink for too-large / quota-exceeded 413s, refetch for 412 revision_mismatch / invalid_if_match / 428 precondition_required, fix_route_label for 403 forbidden_write, rename for 409 manifest_id_immutable / manifest_id_conflict, and migrate_contract for 422 contract_migration_required. Every instructions string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the RateLimit-Reset and Retry-After headers on the same response.
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredWhich input tripped the cap.
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
kindstringrequiredrenameinstructionsstringrequiredkindstringrequiredmigrate_contractinstructionsstringrequiredBearer is for a different app.
okbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
not_foundunknown_operationoperation_not_foundmethod_not_allowedoperation_failedapp_busyvisitor_rate_limitedservice_busyunauthorizedsign_in_requiredtoken_expiredforbiddenaccount_not_joinedforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiunpinned_cdn_scriptinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takeninvalid_domaindomain_takendomain_existsdomain_provider_unavailableapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinewebhook_limit_exceededduplicate_webhookwebhook_disabledversion_limit_exceededplan_requiredstorage_limit_exceededcopy_data_forbiddencopy_data_too_largemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. token_revoked_post_claim is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the recovery field on the same error object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimplanstringPresent on every plan refusal: the tier the caller was refused under. Its presence is what marks an error as a plan refusal rather than a validation or permission failure.
freeprobusinessenterpriselimitstring | integerWhich ceiling the call met, keyed by kind. A plan refusal (*_limit_exceeded) names the countable that ran out — version_history, routines_per_app, routines_per_owner, webhooks_per_app, webhooks_per_owner — and pairs it with max. An app_busy refusal names the bound it met and pairs it with observed and allowed; no plan lifts any of them. Two are per-app run bounds, concurrent_runs and runs_per_window; the third, render_token_refresh, is the page render asking for a new render-token secret, held by 10 per app per client IP and 60 per app across every address in a 60 second window, and observed/allowed name whichever of those two refused. An edits_too_large rejection carries the numeric cap that was exceeded instead of a name.
rungstringOn an app_busy refusal, how hard the app's own refusal ladder is refusing: throttled is the plain ceiling breach above; parked means a caller kept calling inside a wait it was given, so the server mints its own Retry-After (doubling from 60s to a 300s cap) and refuses until a quiet window passes even once the ceiling clears; closed is the same, plus the response closes the connection. Absent on every other kind.
throttledparkedclosedmaxintegerOn a *_limit_exceeded refusal, that limit's number on the caller's plan.
featurestringOn a plan_required refusal, the capability the plan does not include. Never paired with limit / max.
custom_domainwatermark_removalteamsupgradeUrlstring<uri>Absolute link to the owner's own billing page, where the refusal is lifted — the team's page for a team-owned app. Omitted only when the owner has no handle and therefore no settings page of their own, so treat it as optional and fall back to your own copy. MCP appends it as an Upgrade: <url> last line; the CLI prints it under the message.
recoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on kind. Attached to error envelopes the agent can self-correct on: pair for token_revoked_post_claim 401s (#1284), retry for 429s, shrink for too-large / quota-exceeded 413s, refetch for 412 revision_mismatch / invalid_if_match / 428 precondition_required, fix_route_label for 403 forbidden_write, rename for 409 manifest_id_immutable / manifest_id_conflict, and migrate_contract for 422 contract_migration_required. Every instructions string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the RateLimit-Reset and Retry-After headers on the same response.
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredWhich input tripped the cap.
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
kindstringrequiredrenameinstructionsstringrequiredkindstringrequiredmigrate_contractinstructionsstringrequiredApp not found.
okbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
not_foundunknown_operationoperation_not_foundmethod_not_allowedoperation_failedapp_busyvisitor_rate_limitedservice_busyunauthorizedsign_in_requiredtoken_expiredforbiddenaccount_not_joinedforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiunpinned_cdn_scriptinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takeninvalid_domaindomain_takendomain_existsdomain_provider_unavailableapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinewebhook_limit_exceededduplicate_webhookwebhook_disabledversion_limit_exceededplan_requiredstorage_limit_exceededcopy_data_forbiddencopy_data_too_largemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. token_revoked_post_claim is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the recovery field on the same error object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimplanstringPresent on every plan refusal: the tier the caller was refused under. Its presence is what marks an error as a plan refusal rather than a validation or permission failure.
freeprobusinessenterpriselimitstring | integerWhich ceiling the call met, keyed by kind. A plan refusal (*_limit_exceeded) names the countable that ran out — version_history, routines_per_app, routines_per_owner, webhooks_per_app, webhooks_per_owner — and pairs it with max. An app_busy refusal names the bound it met and pairs it with observed and allowed; no plan lifts any of them. Two are per-app run bounds, concurrent_runs and runs_per_window; the third, render_token_refresh, is the page render asking for a new render-token secret, held by 10 per app per client IP and 60 per app across every address in a 60 second window, and observed/allowed name whichever of those two refused. An edits_too_large rejection carries the numeric cap that was exceeded instead of a name.
rungstringOn an app_busy refusal, how hard the app's own refusal ladder is refusing: throttled is the plain ceiling breach above; parked means a caller kept calling inside a wait it was given, so the server mints its own Retry-After (doubling from 60s to a 300s cap) and refuses until a quiet window passes even once the ceiling clears; closed is the same, plus the response closes the connection. Absent on every other kind.
throttledparkedclosedmaxintegerOn a *_limit_exceeded refusal, that limit's number on the caller's plan.
featurestringOn a plan_required refusal, the capability the plan does not include. Never paired with limit / max.
custom_domainwatermark_removalteamsupgradeUrlstring<uri>Absolute link to the owner's own billing page, where the refusal is lifted — the team's page for a team-owned app. Omitted only when the owner has no handle and therefore no settings page of their own, so treat it as optional and fall back to your own copy. MCP appends it as an Upgrade: <url> last line; the CLI prints it under the message.
recoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on kind. Attached to error envelopes the agent can self-correct on: pair for token_revoked_post_claim 401s (#1284), retry for 429s, shrink for too-large / quota-exceeded 413s, refetch for 412 revision_mismatch / invalid_if_match / 428 precondition_required, fix_route_label for 403 forbidden_write, rename for 409 manifest_id_immutable / manifest_id_conflict, and migrate_contract for 422 contract_migration_required. Every instructions string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the RateLimit-Reset and Retry-After headers on the same response.
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredWhich input tripped the cap.
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
kindstringrequiredrenameinstructionsstringrequiredkindstringrequiredmigrate_contractinstructionsstringrequiredIdempotency or manifest identity conflict.
okbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
not_foundunknown_operationoperation_not_foundmethod_not_allowedoperation_failedapp_busyvisitor_rate_limitedservice_busyunauthorizedsign_in_requiredtoken_expiredforbiddenaccount_not_joinedforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiunpinned_cdn_scriptinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takeninvalid_domaindomain_takendomain_existsdomain_provider_unavailableapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinewebhook_limit_exceededduplicate_webhookwebhook_disabledversion_limit_exceededplan_requiredstorage_limit_exceededcopy_data_forbiddencopy_data_too_largemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. token_revoked_post_claim is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the recovery field on the same error object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimplanstringPresent on every plan refusal: the tier the caller was refused under. Its presence is what marks an error as a plan refusal rather than a validation or permission failure.
freeprobusinessenterpriselimitstring | integerWhich ceiling the call met, keyed by kind. A plan refusal (*_limit_exceeded) names the countable that ran out — version_history, routines_per_app, routines_per_owner, webhooks_per_app, webhooks_per_owner — and pairs it with max. An app_busy refusal names the bound it met and pairs it with observed and allowed; no plan lifts any of them. Two are per-app run bounds, concurrent_runs and runs_per_window; the third, render_token_refresh, is the page render asking for a new render-token secret, held by 10 per app per client IP and 60 per app across every address in a 60 second window, and observed/allowed name whichever of those two refused. An edits_too_large rejection carries the numeric cap that was exceeded instead of a name.
rungstringOn an app_busy refusal, how hard the app's own refusal ladder is refusing: throttled is the plain ceiling breach above; parked means a caller kept calling inside a wait it was given, so the server mints its own Retry-After (doubling from 60s to a 300s cap) and refuses until a quiet window passes even once the ceiling clears; closed is the same, plus the response closes the connection. Absent on every other kind.
throttledparkedclosedmaxintegerOn a *_limit_exceeded refusal, that limit's number on the caller's plan.
featurestringOn a plan_required refusal, the capability the plan does not include. Never paired with limit / max.
custom_domainwatermark_removalteamsupgradeUrlstring<uri>Absolute link to the owner's own billing page, where the refusal is lifted — the team's page for a team-owned app. Omitted only when the owner has no handle and therefore no settings page of their own, so treat it as optional and fall back to your own copy. MCP appends it as an Upgrade: <url> last line; the CLI prints it under the message.
recoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on kind. Attached to error envelopes the agent can self-correct on: pair for token_revoked_post_claim 401s (#1284), retry for 429s, shrink for too-large / quota-exceeded 413s, refetch for 412 revision_mismatch / invalid_if_match / 428 precondition_required, fix_route_label for 403 forbidden_write, rename for 409 manifest_id_immutable / manifest_id_conflict, and migrate_contract for 422 contract_migration_required. Every instructions string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the RateLimit-Reset and Retry-After headers on the same response.
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredWhich input tripped the cap.
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
kindstringrequiredrenameinstructionsstringrequiredkindstringrequiredmigrate_contractinstructionsstringrequiredIf-Match did not match the current server revision; response carries the current ETag.
okbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
not_foundunknown_operationoperation_not_foundmethod_not_allowedoperation_failedapp_busyvisitor_rate_limitedservice_busyunauthorizedsign_in_requiredtoken_expiredforbiddenaccount_not_joinedforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiunpinned_cdn_scriptinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takeninvalid_domaindomain_takendomain_existsdomain_provider_unavailableapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinewebhook_limit_exceededduplicate_webhookwebhook_disabledversion_limit_exceededplan_requiredstorage_limit_exceededcopy_data_forbiddencopy_data_too_largemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. token_revoked_post_claim is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the recovery field on the same error object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimplanstringPresent on every plan refusal: the tier the caller was refused under. Its presence is what marks an error as a plan refusal rather than a validation or permission failure.
freeprobusinessenterpriselimitstring | integerWhich ceiling the call met, keyed by kind. A plan refusal (*_limit_exceeded) names the countable that ran out — version_history, routines_per_app, routines_per_owner, webhooks_per_app, webhooks_per_owner — and pairs it with max. An app_busy refusal names the bound it met and pairs it with observed and allowed; no plan lifts any of them. Two are per-app run bounds, concurrent_runs and runs_per_window; the third, render_token_refresh, is the page render asking for a new render-token secret, held by 10 per app per client IP and 60 per app across every address in a 60 second window, and observed/allowed name whichever of those two refused. An edits_too_large rejection carries the numeric cap that was exceeded instead of a name.
rungstringOn an app_busy refusal, how hard the app's own refusal ladder is refusing: throttled is the plain ceiling breach above; parked means a caller kept calling inside a wait it was given, so the server mints its own Retry-After (doubling from 60s to a 300s cap) and refuses until a quiet window passes even once the ceiling clears; closed is the same, plus the response closes the connection. Absent on every other kind.
throttledparkedclosedmaxintegerOn a *_limit_exceeded refusal, that limit's number on the caller's plan.
featurestringOn a plan_required refusal, the capability the plan does not include. Never paired with limit / max.
custom_domainwatermark_removalteamsupgradeUrlstring<uri>Absolute link to the owner's own billing page, where the refusal is lifted — the team's page for a team-owned app. Omitted only when the owner has no handle and therefore no settings page of their own, so treat it as optional and fall back to your own copy. MCP appends it as an Upgrade: <url> last line; the CLI prints it under the message.
recoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on kind. Attached to error envelopes the agent can self-correct on: pair for token_revoked_post_claim 401s (#1284), retry for 429s, shrink for too-large / quota-exceeded 413s, refetch for 412 revision_mismatch / invalid_if_match / 428 precondition_required, fix_route_label for 403 forbidden_write, rename for 409 manifest_id_immutable / manifest_id_conflict, and migrate_contract for 422 contract_migration_required. Every instructions string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the RateLimit-Reset and Retry-After headers on the same response.
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredWhich input tripped the cap.
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
kindstringrequiredrenameinstructionsstringrequiredkindstringrequiredmigrate_contractinstructionsstringrequiredSource exceeds the contract limits.
okbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
not_foundunknown_operationoperation_not_foundmethod_not_allowedoperation_failedapp_busyvisitor_rate_limitedservice_busyunauthorizedsign_in_requiredtoken_expiredforbiddenaccount_not_joinedforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiunpinned_cdn_scriptinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takeninvalid_domaindomain_takendomain_existsdomain_provider_unavailableapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinewebhook_limit_exceededduplicate_webhookwebhook_disabledversion_limit_exceededplan_requiredstorage_limit_exceededcopy_data_forbiddencopy_data_too_largemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. token_revoked_post_claim is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the recovery field on the same error object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimplanstringPresent on every plan refusal: the tier the caller was refused under. Its presence is what marks an error as a plan refusal rather than a validation or permission failure.
freeprobusinessenterpriselimitstring | integerWhich ceiling the call met, keyed by kind. A plan refusal (*_limit_exceeded) names the countable that ran out — version_history, routines_per_app, routines_per_owner, webhooks_per_app, webhooks_per_owner — and pairs it with max. An app_busy refusal names the bound it met and pairs it with observed and allowed; no plan lifts any of them. Two are per-app run bounds, concurrent_runs and runs_per_window; the third, render_token_refresh, is the page render asking for a new render-token secret, held by 10 per app per client IP and 60 per app across every address in a 60 second window, and observed/allowed name whichever of those two refused. An edits_too_large rejection carries the numeric cap that was exceeded instead of a name.
rungstringOn an app_busy refusal, how hard the app's own refusal ladder is refusing: throttled is the plain ceiling breach above; parked means a caller kept calling inside a wait it was given, so the server mints its own Retry-After (doubling from 60s to a 300s cap) and refuses until a quiet window passes even once the ceiling clears; closed is the same, plus the response closes the connection. Absent on every other kind.
throttledparkedclosedmaxintegerOn a *_limit_exceeded refusal, that limit's number on the caller's plan.
featurestringOn a plan_required refusal, the capability the plan does not include. Never paired with limit / max.
custom_domainwatermark_removalteamsupgradeUrlstring<uri>Absolute link to the owner's own billing page, where the refusal is lifted — the team's page for a team-owned app. Omitted only when the owner has no handle and therefore no settings page of their own, so treat it as optional and fall back to your own copy. MCP appends it as an Upgrade: <url> last line; the CLI prints it under the message.
recoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on kind. Attached to error envelopes the agent can self-correct on: pair for token_revoked_post_claim 401s (#1284), retry for 429s, shrink for too-large / quota-exceeded 413s, refetch for 412 revision_mismatch / invalid_if_match / 428 precondition_required, fix_route_label for 403 forbidden_write, rename for 409 manifest_id_immutable / manifest_id_conflict, and migrate_contract for 422 contract_migration_required. Every instructions string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the RateLimit-Reset and Retry-After headers on the same response.
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredWhich input tripped the cap.
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
kindstringrequiredrenameinstructionsstringrequiredkindstringrequiredmigrate_contractinstructionsstringrequiredInvalid manifest, import/dependency mismatch, or required explicit migration.
okbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
not_foundunknown_operationoperation_not_foundmethod_not_allowedoperation_failedapp_busyvisitor_rate_limitedservice_busyunauthorizedsign_in_requiredtoken_expiredforbiddenaccount_not_joinedforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiunpinned_cdn_scriptinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takeninvalid_domaindomain_takendomain_existsdomain_provider_unavailableapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinewebhook_limit_exceededduplicate_webhookwebhook_disabledversion_limit_exceededplan_requiredstorage_limit_exceededcopy_data_forbiddencopy_data_too_largemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. token_revoked_post_claim is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the recovery field on the same error object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimplanstringPresent on every plan refusal: the tier the caller was refused under. Its presence is what marks an error as a plan refusal rather than a validation or permission failure.
freeprobusinessenterpriselimitstring | integerWhich ceiling the call met, keyed by kind. A plan refusal (*_limit_exceeded) names the countable that ran out — version_history, routines_per_app, routines_per_owner, webhooks_per_app, webhooks_per_owner — and pairs it with max. An app_busy refusal names the bound it met and pairs it with observed and allowed; no plan lifts any of them. Two are per-app run bounds, concurrent_runs and runs_per_window; the third, render_token_refresh, is the page render asking for a new render-token secret, held by 10 per app per client IP and 60 per app across every address in a 60 second window, and observed/allowed name whichever of those two refused. An edits_too_large rejection carries the numeric cap that was exceeded instead of a name.
rungstringOn an app_busy refusal, how hard the app's own refusal ladder is refusing: throttled is the plain ceiling breach above; parked means a caller kept calling inside a wait it was given, so the server mints its own Retry-After (doubling from 60s to a 300s cap) and refuses until a quiet window passes even once the ceiling clears; closed is the same, plus the response closes the connection. Absent on every other kind.
throttledparkedclosedmaxintegerOn a *_limit_exceeded refusal, that limit's number on the caller's plan.
featurestringOn a plan_required refusal, the capability the plan does not include. Never paired with limit / max.
custom_domainwatermark_removalteamsupgradeUrlstring<uri>Absolute link to the owner's own billing page, where the refusal is lifted — the team's page for a team-owned app. Omitted only when the owner has no handle and therefore no settings page of their own, so treat it as optional and fall back to your own copy. MCP appends it as an Upgrade: <url> last line; the CLI prints it under the message.
recoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on kind. Attached to error envelopes the agent can self-correct on: pair for token_revoked_post_claim 401s (#1284), retry for 429s, shrink for too-large / quota-exceeded 413s, refetch for 412 revision_mismatch / invalid_if_match / 428 precondition_required, fix_route_label for 403 forbidden_write, rename for 409 manifest_id_immutable / manifest_id_conflict, and migrate_contract for 422 contract_migration_required. Every instructions string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the RateLimit-Reset and Retry-After headers on the same response.
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredWhich input tripped the cap.
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
kindstringrequiredrenameinstructionsstringrequiredkindstringrequiredmigrate_contractinstructionsstringrequiredESM saves require desired-source If-Match.
okbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
not_foundunknown_operationoperation_not_foundmethod_not_allowedoperation_failedapp_busyvisitor_rate_limitedservice_busyunauthorizedsign_in_requiredtoken_expiredforbiddenaccount_not_joinedforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiunpinned_cdn_scriptinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takeninvalid_domaindomain_takendomain_existsdomain_provider_unavailableapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinewebhook_limit_exceededduplicate_webhookwebhook_disabledversion_limit_exceededplan_requiredstorage_limit_exceededcopy_data_forbiddencopy_data_too_largemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. token_revoked_post_claim is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the recovery field on the same error object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimplanstringPresent on every plan refusal: the tier the caller was refused under. Its presence is what marks an error as a plan refusal rather than a validation or permission failure.
freeprobusinessenterpriselimitstring | integerWhich ceiling the call met, keyed by kind. A plan refusal (*_limit_exceeded) names the countable that ran out — version_history, routines_per_app, routines_per_owner, webhooks_per_app, webhooks_per_owner — and pairs it with max. An app_busy refusal names the bound it met and pairs it with observed and allowed; no plan lifts any of them. Two are per-app run bounds, concurrent_runs and runs_per_window; the third, render_token_refresh, is the page render asking for a new render-token secret, held by 10 per app per client IP and 60 per app across every address in a 60 second window, and observed/allowed name whichever of those two refused. An edits_too_large rejection carries the numeric cap that was exceeded instead of a name.
rungstringOn an app_busy refusal, how hard the app's own refusal ladder is refusing: throttled is the plain ceiling breach above; parked means a caller kept calling inside a wait it was given, so the server mints its own Retry-After (doubling from 60s to a 300s cap) and refuses until a quiet window passes even once the ceiling clears; closed is the same, plus the response closes the connection. Absent on every other kind.
throttledparkedclosedmaxintegerOn a *_limit_exceeded refusal, that limit's number on the caller's plan.
featurestringOn a plan_required refusal, the capability the plan does not include. Never paired with limit / max.
custom_domainwatermark_removalteamsupgradeUrlstring<uri>Absolute link to the owner's own billing page, where the refusal is lifted — the team's page for a team-owned app. Omitted only when the owner has no handle and therefore no settings page of their own, so treat it as optional and fall back to your own copy. MCP appends it as an Upgrade: <url> last line; the CLI prints it under the message.
recoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on kind. Attached to error envelopes the agent can self-correct on: pair for token_revoked_post_claim 401s (#1284), retry for 429s, shrink for too-large / quota-exceeded 413s, refetch for 412 revision_mismatch / invalid_if_match / 428 precondition_required, fix_route_label for 403 forbidden_write, rename for 409 manifest_id_immutable / manifest_id_conflict, and migrate_contract for 422 contract_migration_required. Every instructions string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the RateLimit-Reset and Retry-After headers on the same response.
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredWhich input tripped the cap.
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
kindstringrequiredrenameinstructionsstringrequiredkindstringrequiredmigrate_contractinstructionsstringrequiredBuild capacity is full; retry after the returned delay.
okbooleanrequiredfalseerrorobjectrequiredShow propertiesHide properties
kindstringrequiredStable enum-shaped error key. Branch on this for recovery flows.
not_foundunknown_operationoperation_not_foundmethod_not_allowedoperation_failedapp_busyvisitor_rate_limitedservice_busyunauthorizedsign_in_requiredtoken_expiredforbiddenaccount_not_joinedforbidden_writestored_value_too_largestorage_fullinvalid_moduleinvalid_uiunpinned_cdn_scriptinvalid_route_schemainvalid_routes_shapecontract_migration_requiredinvalid_manifest_schemainvalid_manifest_exportsinvalid_requestinvalid_inputinvalid_outputunexpected_keyscapability_deniedcapability_errorexecutor_errorinvalid_call_shapealready_claimedmanifest_not_foundpayload_too_largemodule_too_largeui_too_largedescription_too_longmissing_descriptioninvalid_descriptionrate_limitedimage_origin_deniedtoo_many_requestsexpiredalready_approvedanon_not_remixabletemplate_listing_incompletetemplate_media_invalidforbidden_template_editinvalid_if_matchprecondition_requiredexpected_revision_requiredidempotency_key_requiredidempotency_conflictcontract_not_enabledapp_build_capacityapp_build_failedapp_build_expiredapp_build_authority_lostapp_build_unavailableapp_build_unsupportedversion_history_unavailableversion_not_restorablerevision_mismatchinvalid_revisioncandidate_effects_unsupportedold_string_not_foundold_string_not_uniqueedits_too_largemanifest_id_conflictmanifest_id_immutabletext_too_largestructured_data_too_largeapp_not_foundfeedback_not_foundfeedback_has_no_reply_recipientasset_too_largeasset_count_exceededasset_quota_exceededasset_invalid_keyasset_invalid_content_typeasset_errorinvalid_idsse_cookie_expiredinvalid_secret_namesecret_too_largesecret_already_existssecret_not_foundinvalid_iconteam_slug_takenalready_membergrantee_not_foundinvite_cap_reachedinvite_sender_blockedread_onlyhandle_takeninvalid_handlename_takeninvalid_domaindomain_takendomain_existsdomain_provider_unavailableapp_unclaimedlink_cap_reachedgrantee_is_ownergrantee_is_selfgrantee_already_has_accessalready_invitedroutine_limit_exceededinvalid_intervalop_requires_inputduplicate_routinewebhook_limit_exceededduplicate_webhookwebhook_disabledversion_limit_exceededplan_requiredstorage_limit_exceededcopy_data_forbiddencopy_data_too_largemessagestringreasonstringSet on 401s to distinguish token failure modes when finer detail is needed. token_revoked_post_claim is the post-#1284 surface for a chrm_app_* that was invalidated by a claim — the recovery field on the same error object carries the self-contained pairing-recovery hint the agent should follow instead of creating a new app.
token_malformedtoken_unknowntoken_revokedtoken_revoked_post_claimplanstringPresent on every plan refusal: the tier the caller was refused under. Its presence is what marks an error as a plan refusal rather than a validation or permission failure.
freeprobusinessenterpriselimitstring | integerWhich ceiling the call met, keyed by kind. A plan refusal (*_limit_exceeded) names the countable that ran out — version_history, routines_per_app, routines_per_owner, webhooks_per_app, webhooks_per_owner — and pairs it with max. An app_busy refusal names the bound it met and pairs it with observed and allowed; no plan lifts any of them. Two are per-app run bounds, concurrent_runs and runs_per_window; the third, render_token_refresh, is the page render asking for a new render-token secret, held by 10 per app per client IP and 60 per app across every address in a 60 second window, and observed/allowed name whichever of those two refused. An edits_too_large rejection carries the numeric cap that was exceeded instead of a name.
rungstringOn an app_busy refusal, how hard the app's own refusal ladder is refusing: throttled is the plain ceiling breach above; parked means a caller kept calling inside a wait it was given, so the server mints its own Retry-After (doubling from 60s to a 300s cap) and refuses until a quiet window passes even once the ceiling clears; closed is the same, plus the response closes the connection. Absent on every other kind.
throttledparkedclosedmaxintegerOn a *_limit_exceeded refusal, that limit's number on the caller's plan.
featurestringOn a plan_required refusal, the capability the plan does not include. Never paired with limit / max.
custom_domainwatermark_removalteamsupgradeUrlstring<uri>Absolute link to the owner's own billing page, where the refusal is lifted — the team's page for a team-owned app. Omitted only when the owner has no handle and therefore no settings page of their own, so treat it as optional and fall back to your own copy. MCP appends it as an Upgrade: <url> last line; the CLI prints it under the message.
recoveryRecoveryPair | RecoveryRetry | RecoveryShrink | RecoveryRefetch | RecoveryFixRouteLabel | RecoveryRename | RecoveryMigrateContractSelf-contained recovery hint, branching on kind. Attached to error envelopes the agent can self-correct on: pair for token_revoked_post_claim 401s (#1284), retry for 429s, shrink for too-large / quota-exceeded 413s, refetch for 412 revision_mismatch / invalid_if_match / 428 precondition_required, fix_route_label for 403 forbidden_write, rename for 409 manifest_id_immutable / manifest_id_conflict, and migrate_contract for 422 contract_migration_required. Every instructions string is a single-paragraph, action-first walk-through. Inlined per ADR 2026-05-06-agent-facing-error-surfaces-self-contain-the-fix.
Show propertiesHide properties
kindstringrequiredpairstartstring<uri>requiredverification_urlstring<uri>requiredinstructionsstringrequiredkindstringrequiredretryretry_after_secintegerrequiredSeconds to wait before retrying. Matches the RateLimit-Reset and Retry-After headers on the same response.
retry_after_urlstring<uri>requiredAbsolute URL to retry verbatim once the wait elapses.
instructionsstringrequiredkindstringrequiredshrinkfieldstringrequiredWhich input tripped the cap.
moduleuistylesdescriptiontextstructured_dataasseteditssecretpayloadsize_bytesintegerrequiredcap_bytesintegerrequiredinstructionsstringrequiredkindstringrequiredrefetchrefetch_urlstring<uri>requiredAbsolute URL to GET for the fresh ETag before retrying with a corrected If-Match.
instructionsstringrequiredkindstringrequiredfix_route_labelinstructionsstringrequiredApp-code recovery: the fix is in the route declaration, NOT in the request. Retrying the same request will fail again.
kindstringrequiredrenameinstructionsstringrequiredkindstringrequiredmigrate_contractinstructionsstringrequired