errors: Add bodies for all error codes with an FAQ page#352
Conversation
Write detail-page bodies for the three revocation-related error codes that had an FAQ page but no Markdown body, verified against the realtime auth code and the token revocation docs: - 40131 (API key revoked): switch to a valid credential; investigate if unexpected. Drop the unsupported "permanently invalidated" claim from the summary, keeping it faithful to the FAQ. - 40133 (wrong API key for token revocation): revoke using the issuing key. - 40141 (token revoked): split into expected vs unexpected cases; note that revocation only invalidates already-issued tokens, so the auth server must also stop re-issuing them. Also sharpen the guidelines: "What you should do" should open on the action, not recap the summary; and add a "No em-dashes" rule across all fields. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the three placement-constraint error codes that had an FAQ page but no Markdown body, verified against common/lib/types/placementconstraints.ts (all HTTP 403): - 40330 (unspecified): read the accompanying message; configure the custom endpoint. - 40331 (incompatible environment / dedicated cluster): route clients to the account's dedicated endpoint via the endpoint client option. - 40332 (incompatible site / region): route clients to a permitted region. Use the canonical .ably.net endpoint hostnames (main.realtime.ably.net, acme.realtime.ably.net) rather than the legacy .ably.io form the code emits, and the current `endpoint` client option rather than the older `environment`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remove "cluster" from the Region row's "Don't use" list in the dictionary. Cluster and region are not confusable concepts: a dedicated cluster is an isolated deployment, not a geographic region, and "cluster" is valid customer-facing terminology for it (as used in the 40331 placement-constraint error). Keep "site" and "datacenter" as the internal synonyms to avoid in favour of "region". Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the eight request- and message-validation error codes that had an FAQ page but no Markdown body, verified against the realtime server, node core, and ably-js (all HTTP 400): - 40001 invalid request body - 40003 invalid request parameter value - 40006 message contains invalid connection ID - 40010 invalid channel name - 40012 invalid client ID - 40013 invalid message data or encoding - 40015 invalid device ID - 40016 invalid message name Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the seven request-handling error codes that had an FAQ page but no Markdown body, verified against the realtime server and node core (all HTTP 400): - 40011 pagination sequence no longer valid (restart the enumeration) - 40017 unsupported protocol version - 40020 batch request error (inspect per-item errors) - 40022 API Streamer no longer offered (decommissioned) - 40030 invalid publish request (unspecified umbrella) - 40031 invalid client-specified message id - 40032 invalid message extras field Note: the 40022 FAQ page is stale (it describes an unrelated Control API error); the registry meaning verified from the raising code is authoritative. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the twelve auth/credential error codes that had an FAQ page but no Markdown body, verified against the realtime server, node core, and ably-js: - 40005 invalid API key or token (400, unparseable credential) - 40100 unauthorized - 40101 authentication failed - 40102 incompatible credentials - 40103 basic auth over non-TLS transport - 40104 token request timestamp outside window - 40105 nonce value replayed - 40106 no valid authentication method provided - 40144 invalid JWT token - 40161 operation requires an identified client - 40170 token callback failed - 40171 token renewal not configured (403) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the six limit error codes that had an FAQ page but no Markdown body: - 40111 account connection limit exceeded (403) - 40112 account message limit exceeded (401) - 40114 account channel limit exceeded (403) - 40115 account request limit exceeded (403) - 40125 application integration limit exceeded (401) - 40127 application API key limit exceeded (401) Focus remediation on restoring service: for the package-tied limits (connections, messages, channels, requests) upgrade the package or request a higher limit from support, with the incident escalation process called out for Enterprise customers; the integration-rule and API-key limits are fixed across packages, so they route to support only. Link the canonical pricing/limits and support pages. Statuses and messages verified against account.ts and the node core where raised; the account-wide codes are data-driven so status is taken from the block/restriction defaults. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the seven connection-lifecycle error codes that had an FAQ page but no Markdown body, verified against ably-js connectionerrors.ts, the node core, and the realtime comet transport: - 80000 connection failed (terminal; call connect() after fixing the cause) - 80002 connection suspended (self-healing; history to catch up) - 80014 connection timed out (auto-retried) - 80016 connection replaced by a newer one (non-fatal, 410) - 80017 connection closed (deliberate, 400) - 80019 token request failed (authUrl/authCallback, 401/403) - 80022 connection not found (non-fatal routing, 410) Keep the prose in customer terms (connection, not transport), and point suspended-state readers at the connection state change reason and the history API rather than vague network advice. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the two account-wide creation-rate error codes that had an FAQ page but no Markdown body, verified against account.ts: - 80021 account-wide connection creation rate exceeded (fatal, 429) - 90021 account-wide channel creation rate exceeded (non-fatal, 429) Follow the existing instantaneous rate-limit family's style (42917/42918). The fatal/non-fatal split and message form are taken from the raising code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the nine LiveObjects error codes that had an FAQ page but no Markdown body, verified against the realtime server (lib/errors/helpers.go) and the ably-js liveobjects plugin: - 92000 invalid LiveObjects message (400) - 92001 LiveObjects limit exceeded (400) - 92002 operation on a deleted object (400) - 92003 root has been deleted (400) - 92004 object not found (404) - 92005 path matched no objects (400) - 92006 operation missing object reference (400) - 92007 operation not valid for the path (400) - 92008 sync did not complete (400) Correct the 92001 summary: the raising code enforces a size limit (channel total object size, and per-object max message size), not a maximum number of objects as the old summary and FAQ stated. Its remediation distinguishes the package-tied max message size (upgrade) from the fixed 6.5 MB per-channel total (support). Regenerate protocol/errors.json for the 92001 summary change. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the three channel error codes that had an FAQ page but no Markdown body, verified against ably-js realtimechannel.ts and the realtime server: - 90001 channel in an invalid state for the operation (SDK 400 / server 404) - 90007 channel operation timed out (408; attach/detach, self-healing) - 90010 too many channels (400; per-connection and per-batch-request limits) For 90001, give state-specific recovery (inspect the channel error reason; attach() to recover a failed channel; suspended re-attaches automatically; detach before release) rather than the FAQ's non-idiomatic "operate inside state-change callbacks" advice. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the four presence error codes that had an FAQ page but no Markdown body, verified against ably-js realtimepresence.ts, the node core, and the SDKs (all HTTP 400): - 91000 cannot enter presence without a clientId - 91001 cannot enter presence in the channel's current state - 91003 too many presence members (per-channel, fixed across packages) - 91005 presence state out of sync (get during suspended) 91003 routes to support rather than a package upgrade, since the per-channel presence member limit is the same on every package. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the six LiveSync (Ingress) error codes that had an FAQ page but no Markdown body, verified against the realtime server (lib/errors/helpers.go): - 72000 connector operation failed (500, unexpected internal error) - 72003 cannot reach the database (500) - 72004 could not identify target channel (400, missing _ablyChannel) - 72005 MongoDB pipeline is invalid (400) - 72006 failed to resume (500, unreadable resume token) - 72007 failed to track its position (500, ably collection permissions) Use the customer-facing "LiveSync connector" terminology throughout rather than the internal "Ingress"/"rule worker" names, while quoting the raw message strings verbatim in What you'll see. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Write detail-page bodies for the five Spaces error codes that had an FAQ page but no Markdown body, verified against the @ably/spaces SDK (src/Errors.ts, all HTTP 400): - 101000 space name is empty - 101001 space must be entered first - 101002 lock request already pending - 101003 lock already held - 101004 lock invalidated by concurrent request The lock errors frame contention as expected behaviour and point at the Spaces locking documentation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ption errors Write detail-page bodies for the remaining twelve error codes that had an FAQ page but no Markdown body, verified against the realtime server, node core, ably-js, and the bundled canonical messages: - 10000 no error / 20000 general error (placeholders/catch-all) - 40000 bad request (400) / 40300 forbidden (403) / 40400 not found (404) - 50000 internal server error (500) - 40311 application requires a TLS connection (403) - 50001 internal channel error (500) / 50002 internal connection error (500) - 50003 request timed out server-side (503, some paths 500) - 93002 message annotations/updates/appends/deletes not enabled (400) - 71302 no subscription to product 40300 links the capability docs; 93002 uses the annotations and updates-deletes docs' own terminology rather than "mutable messages". 71302's FAQ page is gone and its raising code is not in the cloned repos, so its body follows the registry summary and canonical message without asserting a status. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update the twelve pre-existing rate/size-limit bodies that linked https://ably.com/docs/general/limits (which 301-redirects) to the canonical https://ably.com/docs/platform/pricing/limits, matching the URL used by the bodies written in this pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rewrite the em-dash asides in 26 existing entries (including the 40142 worked example) into plain sentences, per the "No em-dashes" guideline: commas for brief asides, colons or sentence splits for elaborations, and parentheses for appositives such as the push-provider lists. Wording and meaning are unchanged; only punctuation is affected. Quoted message strings are left verbatim. Regenerate protocol/errors.json for the summaries that changed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Each body-bearing entry ended with a blank line before EOF, which markdownlint flags as MD012 (no-multiple-blanks) in the documentation format check. Normalize every codes/*.md to end with a single newline. Whitespace only; no content changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
m-hulbert
left a comment
There was a problem hiding this comment.
Mostly looks good to me, thanks @lmars !
Just a few relatively minor suggested fixes and changes:
- Since it's only docs consuming these, can we make the links relative
/docs/channels/... - Do we want to advertise incident escalation for enterprise packages on the rate limits? Or should we at least qualify it with something around out of hours or urgency?
- I think the support links should go to support rather than ading another hop via the docs page.
- We've still got a few instances of 'channel rule' creeping in.
- I've updated dashboard links to link to the relevant dashboard page - might be worth updating the guidelines?
|
|
||
| ## What you should do | ||
|
|
||
| Rely on the accompanying message and HTTP status for the specifics, since 20000 itself only signals that the condition didn't map to a more specific code. Capture the message and status, and if the cause isn't clear, [contact Ably support](https://ably.com/docs/platform/support) with them. |
There was a problem hiding this comment.
| Rely on the accompanying message and HTTP status for the specifics, since 20000 itself only signals that the condition didn't map to a more specific code. Capture the message and status, and if the cause isn't clear, [contact Ably support](https://ably.com/docs/platform/support) with them. | |
| Rely on the accompanying message and HTTP status for the specifics, since 20000 itself only signals that the condition didn't map to a more specific code. Capture the message and status, and if the cause isn't clear, [contact Ably support](https://ably.com/support) with them. |
|
|
||
| ## What you should do | ||
|
|
||
| Check the API key or token the client was configured with. The value couldn't be read at all, so the fix is to supply a correctly-formed credential, not to adjust its permissions. Copy the key from the [Ably dashboard](https://ably.com/dashboard) again in case it was truncated or picked up stray whitespace. |
There was a problem hiding this comment.
| Check the API key or token the client was configured with. The value couldn't be read at all, so the fix is to supply a correctly-formed credential, not to adjust its permissions. Copy the key from the [Ably dashboard](https://ably.com/dashboard) again in case it was truncated or picked up stray whitespace. | |
| Check the API key or token the client was configured with. The value couldn't be read at all, so the fix is to supply a correctly-formed credential, not to adjust its permissions. Copy the key from the [Ably dashboard](https://ably.com/accounts/any/apps/any/app_keys) again in case it was truncated or picked up stray whitespace. |
|
|
||
| ## What you should do | ||
|
|
||
| API Streamer has been shut down, so requests that depend on it can't be served and won't recover. If your application still targets it, migrate to a current Ably integration. Contact Ably support if you're unsure what replaces your use case. |
There was a problem hiding this comment.
| API Streamer has been shut down, so requests that depend on it can't be served and won't recover. If your application still targets it, migrate to a current Ably integration. Contact Ably support if you're unsure what replaces your use case. | |
| API Streamer has been shut down, so requests that depend on it can't be served and won't recover. If your application still targets it, migrate to a current Ably integration. Contact [Ably support](https://ably.com/support) if you're unsure what replaces your use case. |
|
|
||
| ## What you should do | ||
|
|
||
| Restore service by upgrading the account to a package with a higher [connection limit](https://ably.com/docs/platform/pricing/limits), or, if you need more than the packages provide, by [contacting Ably support](https://ably.com/docs/platform/support) to request a higher limit. Enterprise customers whose service is disrupted can use the [incident escalation process](https://ably.com/docs/platform/support#escalation) to page Ably's engineering team at any time. |
There was a problem hiding this comment.
| Restore service by upgrading the account to a package with a higher [connection limit](https://ably.com/docs/platform/pricing/limits), or, if you need more than the packages provide, by [contacting Ably support](https://ably.com/docs/platform/support) to request a higher limit. Enterprise customers whose service is disrupted can use the [incident escalation process](https://ably.com/docs/platform/support#escalation) to page Ably's engineering team at any time. | |
| Restore service by upgrading the account to a package with a higher [connection limit](https://ably.com/docs/platform/pricing/limits), or, if you need more than the packages provide, by [contacting Ably support](https://ably.com/support) to request a higher limit. Enterprise customers whose service is disrupted can use the [incident escalation process](https://ably.com/docs/platform/support#escalation) to page Ably's engineering team at any time. |
|
|
||
| ## What you should do | ||
|
|
||
| Move the client onto a different, valid credential. If you administer the account, select another active API key in the [Ably dashboard](https://ably.com/dashboard) or create a new one; if the client uses [token authentication](https://ably.com/docs/auth/token), issue its tokens from that key instead. If you don't administer the account, ask an admin to do this and to provide the key or a token request generated from it. |
There was a problem hiding this comment.
| Move the client onto a different, valid credential. If you administer the account, select another active API key in the [Ably dashboard](https://ably.com/dashboard) or create a new one; if the client uses [token authentication](https://ably.com/docs/auth/token), issue its tokens from that key instead. If you don't administer the account, ask an admin to do this and to provide the key or a token request generated from it. | |
| Move the client onto a different, valid credential. If you administer the account, select another active API key in the [Ably dashboard](https://ably.com/accounts/any/apps/any/app_keys) or create a new one; if the client uses [token authentication](https://ably.com/docs/auth/token), issue its tokens from that key instead. If you don't administer the account, ask an admin to do this and to provide the key or a token request generated from it. |
| If the message matters, republish it after a short delay, increasing the delay if it is rejected again. | ||
|
|
||
| To keep within the limit, consider [spreading publishing across more channels](https://faqs.ably.com/how-do-i-avoid-hitting-the-max-channel-message-rate-limit), so traffic is divided between them rather than concentrated on one. If a channel genuinely needs a higher rate, you can [request a higher limit](https://ably.com/docs/general/limits). | ||
| To keep within the limit, consider [spreading publishing across more channels](https://faqs.ably.com/how-do-i-avoid-hitting-the-max-channel-message-rate-limit), so traffic is divided between them rather than concentrated on one. If a channel genuinely needs a higher rate, you can [request a higher limit](https://ably.com/docs/platform/pricing/limits). |
There was a problem hiding this comment.
Would prefer to not link to an FAQ since we're switching them off.
…ology Apply Mark's review feedback on the error-code bodies: - Point "contact Ably support" links at https://ably.com/support instead of hopping through the docs/platform/support page (16 files). Keep the #escalation anchor on docs, where the escalation process is documented. - Link dashboard actions to the specific page (the app's API keys page) rather than the dashboard root (40005, 40131). - Replace the compound "channel rule" with namespace-centric wording in the flagged bodies (40161, 93002), matching Ably's docs which lead with "namespace" and reserve "rule" for an individual named setting. - Qualify the incident-escalation note on account-limit errors so it applies to production-disrupting, urgent cases rather than "at any time" (40111, 40112, 40114, 40115). - Codify all of the above in guidelines.md and CLAUDE.md: link dashboard actions to the specific page, send support links to the support page, and prefer "namespace"/"namespace settings" over "channel rule". No frontmatter changed, so protocol/errors.json needs no regeneration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
@m-hulbert I've addressed most of your feedback in e06de73, except the following:
I don't think it's only docs consuming these, we haven't decided yet but we might want to include the "What you should do" sections as hints in errors over the wire, so I've kept them absolute for now.
I think so yes, so I've qualified it.
I asked Claude to search for equivalent guidance in the docs and I couldn't find it, so I've left the FAQ link because I think it's better to link to something, and then we can replace in the future when we migrate the pages to the docs. |
Summary
Writes detail-page Markdown bodies for every error code that had an FAQ page referenced in
protocol/errorsHelp.jsonbut no body yet — 79 codes in total. The goal is to make the new website error pages (ably.com/docs/platform/errors/codes) self-sufficient so the oldfaqs.ably.comlinks can eventually be retired.Each body follows the three-section format in
errors/guidelines.md(What you should do → Why it happens → What you'll see) and was verified against source, not the FAQ text alone: the realtime server, the node core,ably-js,@ably/spaces, and the bundled canonical messages. Message strings and HTTP statuses in What you'll see come from the raising code.What's included
Bodies were added in batches by domain:
Guidelines & terminology changes
Corrections found while verifying against source
protocol/errors.jsonregenerated.Housekeeping
/docs/general/limitsURL to the canonical/docs/platform/pricing/limits.40142.mdworked example) to satisfy the new guideline; wording unchanged, punctuation only.All changes pass
npm run validate:errors, andprotocol/errors.jsonis regenerated wherever a summary changed.🤖 Generated with Claude Code