Skip to content

feat(core): add TAPI error classification types and utilities#1156

Open
abueide wants to merge 9 commits intomasterfrom
tapi/types-and-errors
Open

feat(core): add TAPI error classification types and utilities#1156
abueide wants to merge 9 commits intomasterfrom
tapi/types-and-errors

Conversation

@abueide
Copy link
Contributor

@abueide abueide commented Mar 10, 2026

Summary

  • Add foundation types: HttpConfig, BackoffConfig, RateLimitConfig, ErrorClassification, and related config fields to Config and SegmentAPISettings
  • Add error classification utilities: classifyError(), parseRetryAfter(), and improved translateHTTPError()
  • Add comprehensive test suite (35 tests) covering status code classification, retry-after parsing, and SDD-specified overrides
  • Fix parseRetryAfter to use strict /^\d+$/ regex instead of parseInt, preventing date strings starting with digits from being misclassified as seconds
  • Add test for 429 + statusCodeOverride='drop' precedence behavior
  • Add test for date-string-starting-with-digits edge case
  • Fix formatting in e2e-cli files to pass CI format-check

PR 1 of 5 in the TAPI backoff/retry stack. See #1154 for full context.

Test plan

  • All 35 error classification tests pass
  • parseRetryAfter("01 Jan 2026 00:01:00 GMT") correctly parses as date (60s), not as integer (1s)
  • classifyError(429, { statusCodeOverrides: { '429': 'drop' } }) returns permanent
  • CI format-check passes

🤖 Generated with Claude Code

abueide and others added 6 commits March 12, 2026 11:10
Add foundation types (HttpConfig, BackoffConfig, RateLimitConfig,
ErrorClassification) and error classification utilities (classifyError,
parseRetryAfter, translateHTTPError improvements) for TAPI-compliant
retry handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remnants from the removed BackoffManager and UploadStateMachine classes,
never imported anywhere.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Convert ErrorClassification from a plain type to a class with a getter,
eliminating redundant isRetryable field that was always derivable from
errorType !== 'permanent'.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
parseRetryAfter now returns undefined for negative seconds instead
of falling through to date parsing where the behavior was ambiguous.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…verage

Use regex /^\d+$/ instead of parseInt to prevent date strings starting
with digits from being misclassified as seconds. Add test for
429+override='drop' precedence and date-string edge case. Run formatter
to fix CI.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@abueide abueide force-pushed the tapi/types-and-errors branch from eedad38 to 36997ac Compare March 12, 2026 16:11
abueide and others added 3 commits March 12, 2026 11:30
Restore JSDoc on ErrorType enum and inline comments in
translateHTTPError that were inadvertently removed during cleanup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* - 'lazy' (default): uses the longest wait time (most conservative, fewer retries)
* - 'eager': uses the shortest wait time (more aggressive, retries sooner)
*/
retryStrategy?: 'eager' | 'lazy';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it conceptually, but adding a parameter for RN that's not in the kotlin (and eventually swift) changes affects SDK parity. I think it's ok for us to express a firm opinion (i.e. only implement lazy until we learn it's needed), this is how we interact with our own server after all. I'm more ok with that opinion differing between libs than the options differing.

Do argue if you think it's important to how RN works specifically :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the reason is that because of the way react native is different and we're using global retry tracking only instead of per-batch I needed some heuristic to calculate which batch response "wins". I figured if I do that I might as well make it flexible in the code in case we want to change it or something, but I don't necessarily have a preference one way or the other.

* When true, automatically triggers a flush when the retry manager's wait
* period expires and transitions back to READY. Disabled by default.
*/
autoFlushOnRetryReady?: boolean;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

likewise. Part of me wants this to go in every SDK, but I think existing flush policy with timers is enough control for users.

Open to debating it tho

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can agree I don't have any qualms with removing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants