src/lib/http.ts has no AbortController or AbortSignal. Its setTimeout calls (:77, :83) are retry backoff delays only.
A stalled connection therefore hangs indefinitely, and the retry loop at :42-95 never fires — because nothing ever fails. MAX_RETRIES and the exponential backoff are inert against the one failure mode they cannot observe.
The pattern already exists elsewhere in this codebase:
src/lib/upload.ts:82-83 — AbortController + 15s abort
src/lib/posters.ts:49-50 — AbortController + 10s abort
The primary transport just never got it, so every apiRequest call across all 20 endpoints is exposed.
Fix
- Wrap
fetch in an AbortController with a configurable timeout (e.g. PARTIFUL_TIMEOUT_MS, default ~30s), applied to all four transports (http.ts:104,144,174,203).
- Treat the abort as a retryable error so it feeds the existing backoff rather than failing outright.
- Add a test that asserts a stalled request aborts and retries.
Related
Part of the same failure family as the Retry-After NaN bug — the retry/transport layer degrades badly under exactly the adverse network conditions it exists to handle.
src/lib/http.tshas noAbortControllerorAbortSignal. ItssetTimeoutcalls (:77,:83) are retry backoff delays only.A stalled connection therefore hangs indefinitely, and the retry loop at
:42-95never fires — because nothing ever fails.MAX_RETRIESand the exponential backoff are inert against the one failure mode they cannot observe.The pattern already exists elsewhere in this codebase:
src/lib/upload.ts:82-83—AbortController+ 15s abortsrc/lib/posters.ts:49-50—AbortController+ 10s abortThe primary transport just never got it, so every
apiRequestcall across all 20 endpoints is exposed.Fix
fetchin anAbortControllerwith a configurable timeout (e.g.PARTIFUL_TIMEOUT_MS, default ~30s), applied to all four transports (http.ts:104,144,174,203).Related
Part of the same failure family as the
Retry-AfterNaN bug — the retry/transport layer degrades badly under exactly the adverse network conditions it exists to handle.