HTTP errors (4xx, 5xx status codes) don't automatically throw exceptions in fetch().
The Promise resolves successfully — you must check response.ok or
response.status to detect errors.
This is one of the most common mistakes when using fetch(). Always check for errors
before parsing the response body.
The Problem: Errors Don't Throw
// This does NOT throw for 404 or 500 errors!const response = awaitfetch('/api/users/999');
// response.ok is false for 4xx/5xx status codes
console.log(response.ok); // false
console.log(response.status); // 404// The body might contain an error message from the serverconst data = await response.json();
console.log(data); // { error: "User not found" }
fetch() only rejects for network errors (no connection, DNS failure).
HTTP error responses are still valid responses — the server responded, just with an error status.
The Solution: Check response.ok
async functionfetchData(url) {
const response = awaitfetch(url);
if (!response.ok) {
// Try to get error details from response bodylet errorMessage = `HTTP ${response.status}`;
try {
const errorData = await response.json();
errorMessage = errorData.message || errorData.error || errorMessage;
} catch {
// Response wasn't JSON, use status text
errorMessage = response.statusText || errorMessage;
}
throw newError(errorMessage);
}
return response.json();
}
// Usagetry {
const user = awaitfetchData('/api/users/999');
} catch (error) {
console.error('Request failed:', error.message);
// Show user-friendly error message
}