DEV3 Technologies home

DEV3 Developer Forum

Why does fetch not throw on a 404 or 500 response in JavaScript?

JavaScript helpSolved0 views
dev3 ·

I wrapped fetch in try/catch but my catch block never runs when the server returns 404 or 500. How do I handle HTTP errors correctly?

#javascript#fetch#error-handling

0

1 reply

dev3 · Accepted answer

fetch rejects only on network-level failures (DNS, offline, CORS block, aborted request). An HTTP error status still resolves with a Response whose ok is false.

async function getJSON(url, options) {
  const res = await fetch(url, options);

  if (!res.ok) {
    // read the body for details if the API sends JSON errors
    let detail = '';
    try { detail = await res.text(); } catch {}
    throw new Error(`HTTP ${res.status} ${res.statusText}: ${detail.slice(0, 200)}`);
  }

  // 204 has no body
  if (res.status === 204) return null;
  return res.json();
}

try {
  const data = await getJSON('/api/items');
} catch (err) {
  console.error(err);   // network failure OR HTTP error
}

Details

  • res.ok is true for status 200 to 299.
  • The body can be read once. Use res.clone() if you need it twice.
  • res.json() throws SyntaxError if the body is not JSON (for example an HTML error page). Check content-type or read text() first when unsure.
  • Sending JSON needs both the header and a string body:
await fetch('/api/items', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ name: 'x' }),
});
  • Cookies: cross-origin requests need credentials: 'include'.
  • Axios, by contrast, rejects on non-2xx by default, which is why people are surprised.

Pitfall: a CORS failure shows as TypeError: Failed to fetch with no status information. Check the browser Network tab and the server's CORS headers.

0

Your reply

Every post is reviewed by DEV3 before it appears. Usually reviewed within 24 hours.

Markdown supported. Use ``` for code blocks. Images are not allowed.