fix(errors): correct the API error code table and export the helpers - #1867
Open
MartinCupela wants to merge 1 commit into
Open
MartinCupela wants to merge 1 commit into
MartinCupela wants to merge 1 commit into
Conversation
MartinCupela
requested review from
isekovanic,
oliverlaz,
santhoshvai,
szuperaz and
vishalnarkhede
as code owners
September 14, 2026 14:47
The table in errors.ts had drifted from the codes the API actually sends. Four entries had no server-side counterpart at all, and 17 codes were missing, so isErrorRetryable silently fell through to "not retryable" for errors that are transient. Renumber the two codes that were simply wrong: auth failure is 5, not 3, and request timeout is 48, not 23. Their retryable flags carry over unchanged. Drop 24 (MaxHeaderSizeExceededError) and 69 (ErrWrongRegion), which the API does not define. Add the 19 remaining codes, grouped by area. The retryable flag follows the rule the existing entries imply: true when the identical request may succeed later with no action from the caller (overload, timeout, capacity), false when something must change first (input, credentials, permissions, app config). That rule also makes 82 retryable, matching 45 — both wrap an upstream call failure behind a 400. Fix one caller that had been keyed to the wrong code: the offline sync manager skipped its DB reset on code 23, meaning "the sync timed out, keep the data". Since the API never sends 23, that branch never fired and every timed-out sync wiped the offline database instead. Export the module from the package entry point so consumers can reach the helpers, which is what #1848 asked for. Fixes #1848 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
MartinCupela
force-pushed
the
fix/api-error-codes
branch
from
September 14, 2026 14:56
822c666 to
e1525fb
Compare
szuperaz
approved these changes
Sep 14, 2026
isekovanic
approved these changes
Sep 14, 2026
isekovanic
left a comment
Contributor
There was a problem hiding this comment.
Looks good if these indeed changed and need to be regenerated, but is this on the V2 API only ? Or has it always just been broken ?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
CLA
Description of the changes, What, Why and How?
Supersedes #1864, which exports
src/errorsfrom the entry point. That export is included here, but it is not enough on its own: the table it makes public has drifted badly from the codes the API actually sends, so exporting it as-is would turn the drift into public API.I compared
APIErrorCodesagainst the canonical list the API defines. The table had 27 entries; the API defines 44. Four of the 27 have no server-side counterpart at all.Codes that were wrong
3AuthenticationFailedError523RequestTimeoutError4824MaxHeaderSizeExceededError69ErrWrongRegionisErrorRetryablereturnsfalseon a table miss, so a real 408 was classified as non-retryable andBaseSearchSource/MessageDeliveryReporter/ the WS fallback gave up on timeouts instead of retrying them. The two renumbered entries keep their originalretryableflags.Codes that were missing
19 added, grouped by area:
72,73,80,81,82,100–106,107,108,109,110,111,112,113.Video codes are included even though this client never calls the video endpoints, so the table stays a faithful mirror rather than a partial one. Easy to drop if you'd rather keep it chat-only.
The rule behind
retryableWorth stating, because nothing anywhere defines it and the flags have been hand-maintained since 2021 with no written rationale. HTTP status does not predict it —
60CoolDown and17NotAllowed are both 403 with opposite flags, as are45and44at 400.The rule the existing entries imply: can time alone fix it?
truewhen the identical request, resent unchanged, may succeed later with no action from the caller (overload, timeout, capacity, cooldown expiry).falsewhen something has to change first — input, credentials, permissions, app config, billing state.Applying that rule consistently also flips
82VideoCreateCallFailed totrue: it wraps an upstream video provider failure behind a 400, structurally identical to45CustomCommandEndpointCallError, which has always beentrue.One entry is genuinely undecidable:
101is emitted by two different server constructors, one a 500 (transient) and one a 400 (definitive). A client holding only the code cannot tell them apart. I chosetrue, favouring the 500 flavour, but the real fix is server-side.A bug this turned up
offline_sync_manager.tsskipped itsresetDB()oncode === 23, meaning "the sync timed out, so don't wipe the data — a timeout says nothing about how stale the DB is". Since the API never sends 23, that branch never fired, and every timed-out/syncwiped the offline database instead. Now keyed to 48. An existing test was asserting the broken behaviour with a hand-built code-23 error; updated.Happy to split this into its own PR if you'd rather keep this one to the table.
Testing
One test added, covering the only behaviour here that is not just data:
isErrorRetryablefalling through tofalsefor an unknown code and for an error with no code. The table's contents are not asserted — a test that restates the table would only duplicate it. The existing offline-sync timeout test was updated to the correct code.yarn lint,yarn typesandyarn buildall pass; full suite is 3161 passed / 1 skipped against a 3152 baseline. Verified against the built bundle that the helpers are reachable from the entry point at runtime and thatisErrorRetryable({ code: 48 })is nowtrue.Follow-ups, not in this PR
release-v10carries the same 27-entry table and needs the same fix. Entry names are unchanged here, soisDoesNotExistError(which matches on the name) ports cleanly.unrecoverableflag on error responses, but sets it in only three places server-side. If that were set consistently,isErrorRetryablecould prefer the server's own answer and keep this table as the fallback for older backends — which would stop the drift recurring. Worth raising with the backend team.Changelog
APIErrorCodesentries that did not match the codes the API sends, soisErrorRetryablecorrectly identifies request timeouts and other transient failures as retryableAPIErrorCodes,isAPIError,isErrorRetryable,isConnectionIDError,isWSFailure,isErrorResponse) from the package entry point🤖 Generated with Claude Code