node-fetch
semver
>=2.0.0postconditions11functions5last verified2026-04-03coverage score83%Postconditions — what we check
- fetch · fetch-rejects-on-network-errorerrorWhennetwork failure (DNS resolution failure, connection refused, timeout, etc.)Throws
Promise rejection with FetchError (error.type='system', error.code like ENOTFOUND, ECONNREFUSED, ETIMEDOUT)Required handlingCaller MUST use try-catch to handle Promise rejections from fetch(). Network-level failures (DNS errors, connection refused, timeouts) reject the Promise. CRITICAL: fetch() does NOT reject on HTTP 4xx/5xx status codes - those are successful responses that must be checked with response.ok. Recommended pattern: try { const res = await fetch(url); if (!res.ok) throw new Error(`HTTP ${res.status}`); } catch (error) { /* handle network errors */ }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - fetch · fetch-rejects-on-aborterrorWhenrequest is cancelled via AbortSignal before or during the requestThrows
Promise rejection with AbortError (error.name='AbortError', error.type='aborted')Required handlingWhen using AbortController to cancel requests, the caller MUST handle AbortError separately from FetchError. AbortError is thrown when signal.abort() is called. Pattern: try { const res = await fetch(url, { signal }); } catch (err) { if (err.name === 'AbortError') { /* handle cancellation */ } else throw err; }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisible - fetch · fetch-rejects-on-redirect-errorwarningWhenredirect:error option set and server responds with redirect, OR redirect limit (default 20) exceededThrows
Promise rejection with FetchError (error.type='no-redirect' or error.type='max-redirect')Required handlingWhen fetch() is called with redirect:'error', any redirect response causes rejection with FetchError (error.type='no-redirect'). When redirect limit (default 20) is exhausted, rejects with FetchError (error.type='max-redirect'). Both must be caught.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - fetch · fetch-http-error-not-thrownerrorWhenserver responds with HTTP 4xx or 5xx status codeThrows
DOES NOT throw — resolves with Response object where response.ok === falseRequired handlingCRITICAL FOOTGUN: Unlike axios, node-fetch does NOT reject on HTTP error status codes. HTTP 4xx/5xx resolve successfully to a Response with response.ok === false. Callers MUST explicitly check response.ok or response.status before processing body. Failure silently processes error responses (HTML error pages, error JSON) as valid data. Pattern: if (!response.ok) throw new Error(`HTTP error ${response.status}`);costhighin prodsilent failureusers seelost datavisibilitysilentSources[2] - response.json · response-json-throws-on-invalid-jsonerrorWhenresponse body is not valid JSON (HTML error pages, plain text, empty body from 204 responses)Throws
SyntaxError from JSON.parse() — 'Unexpected token < in JSON at position 0' or similarRequired handlingresponse.json() calls JSON.parse() internally. If the server returns HTML (e.g., error page, WAF block, load balancer error), SyntaxError is thrown. Caller MUST wrap in try-catch. Combine with response.ok check to handle HTTP errors before attempting to parse body. Pattern: if (!response.ok) throw new Error(...); const data = await response.json();costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - response.json · response-json-throws-on-max-sizewarningWhenresponse body size exceeds the size limit set in RequestInit.size optionThrows
FetchError (error.type='max-size') — 'content size at <url> over limit: <size>'Required handlingIf fetch() was called with a size limit option and the response body exceeds it, response.json() throws FetchError with error.type='max-size'. Must be caught with try-catch around response.json().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - response.json · response-json-throws-on-body-usedwarningWhenresponse.json() called after body stream has already been consumed by any body-reading methodThrows
TypeError — 'body used already for: <url>'Required handlingResponse bodies can only be consumed once. Calling response.json() after any other body-consuming method (json, text, blob, arrayBuffer, formData) throws TypeError. Use response.clone() to read the body multiple times. Pattern: const cloned = response.clone(); const data = await cloned.json();costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2] - response.text · response-text-throws-on-stream-errorerrorWhenresponse body stream encounters a system-level error during reading (premature close, network drop after headers received)Throws
FetchError (error.type='system') — 'Invalid response body while trying to fetch <url>'Required handlingEven after a successful fetch() (headers received, Promise resolved), the body stream can fail during reading. response.text() MUST be wrapped in try-catch. FetchError with type='system' indicates a stream-level I/O error. Common mistake: wrapping only fetch() in try-catch, leaving response.text() unguarded.costmediumin prodimmediate exceptionusers seedegraded performancevisibilityvisibleSources[1] - response.text · response-text-throws-on-premature-closeerrorWhenserver closes the connection before the full body is receivedThrows
FetchError — 'Premature close of server response while trying to fetch <url>'Required handlingIf the server closes the TCP connection before sending the full response body, response.text() throws FetchError. This occurs after headers are received but before body completes — distinct from initial fetch() network failure. Must be caught with try-catch around response.text().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - response.blob · response-blob-throws-on-stream-errorerrorWhenresponse body stream fails during reading (system error, premature close, max-size exceeded)Throws
FetchError (error.type='system' or 'max-size') — same errors as response.text()Required handlingresponse.blob() delegates to arrayBuffer() which uses the same consumeBody() stream path. Must be wrapped in try-catch to handle FetchError on stream errors. Same error types apply as response.text() and response.arrayBuffer().costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - response.arrayBuffer · response-arraybuffer-throws-on-stream-errorerrorWhenresponse body stream fails during reading (system error, premature close, or size limit exceeded)Throws
FetchError (error.type='system') or FetchError (error.type='max-size') if size limit exceededRequired handlingresponse.arrayBuffer() uses the same consumeBody() stream-reading path. IMPORTANT for file downloads: max-size option on the original fetch() call will cause FetchError here if the file is larger than the limit. Must be wrapped in try-catch.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1]
Sources
Every postcondition cites at least one of these. Numbered to match the footnotes above.
Need a different package?
Request a profile