You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
web-api v8 no longer retries interrupted response bodies #2738
The call should retry once and return { ok: true, response_metadata: {} }, with { requests: 2 }, as 7.19.0 does.
The automatic retries docs say "The client will retry a failed API method call up to 10 times"; this repro sets retries: 1. The error-handling docs also say SDK errors have a code property.
Actual Result
With 8.1.1, the repro prints:
TypeError terminated undefined
{ requests: 1 }
auth.test() rejects after the first request without retrying. The error is a raw TypeError, and error.code is undefined.
makeRequest() retries fetch(), but buildResult() reads response.text() outside that retry loop. A disconnect while reading the body therefore skips both retrying and error wrapping.
The regression comes from the v7→v8 move from axios to fetch. makeRequest() wraps only the fetch() call in pRetry and returns the Response before its body is read; the body is then read in buildResult() via response.text(), which is both outside the retry loop and outside the try/catch that wraps failures into a coded WebAPIRequestError. So a disconnect while reading a 200 body neither retries nor gets a code (hence error.code === undefined). Under axios the body was materialized inside the retried request, so the same interruption was retried and wrapped.
We'll treat this as a bug on our side. Until it's patched, two options:
Pass a custom fetch that fully buffers the body before returning, so the interruption happens inside the retried/wrapped path (I verified this flips your repro to { requests: 2 } / { ok: true } on 8.1.1):
Activity
WilliamBergamin commentedon Sep 10, 2026
Hi @pkaminski thanks for the exceptionally clear repro and diagnosis 🙏
I was able to confirm this this locally
Reproduced locally with your script:
@slack/web-api@8.1.1→TypeError terminated(error.codeisundefined),{ requests: 1 }(no retry)@slack/web-api@7.19.0→{ ok: true, response_metadata: {} },{ requests: 2 }(retries and succeeds)The regression comes from the v7→v8 move from axios to
fetch.makeRequest()wraps only thefetch()call inpRetryand returns theResponsebefore its body is read; the body is then read inbuildResult()viaresponse.text(), which is both outside the retry loop and outside thetry/catchthat wraps failures into a codedWebAPIRequestError. So a disconnect while reading a 200 body neither retries nor gets acode(henceerror.code === undefined). Under axios the body was materialized inside the retried request, so the same interruption was retried and wrapped.We'll treat this as a bug on our side. Until it's patched, two options:
fetchthat fully buffers the body before returning, so the interruption happens inside the retried/wrapped path (I verified this flips your repro to{ requests: 2 }/{ ok: true }on 8.1.1):fix(web-api): retry responses interrupted while reading the body