---
title: "Fix the Failed to fetch error and tell its 3 causes apart"
description: "TypeError: Failed to fetch means the request got no HTTP response. A missing CORS header, a server that is down, and a host that does not exist all give this same message."
canonical: "https://logbrew.co/en/errors/failed-to-fetch"
last_updated: "2026-11-10"
---

# Fix the Failed to fetch error and tell its 3 causes apart

`TypeError: Failed to fetch` means the request got no HTTP response. A missing CORS header, a server that is down, and a host that does not exist all give this same message.

Tested on November 10, 2026 with Chromium 152, @logbrew/browser 0.1.21, and @logbrew/sdk 0.1.44

By [Furkan Erday](https://github.com/furkanerday). Furkan Erday is the founder of LogBrew. He builds LogBrew with Claude Code and Codex every day.

Canonical: https://logbrew.co/en/errors/failed-to-fetch

## What names the cause of a failed `fetch()`

| What went wrong | `error.message` | Console |
| --- | --- | --- |
| No `Access-Control-Allow-Origin` header | `Failed to fetch` | CORS policy |
| Nothing listens on the port | `Failed to fetch` | `ERR_CONNECTION_REFUSED` |
| The host has no DNS record | `Failed to fetch` | `ERR_NAME_NOT_RESOLVED` |
| The server answered 500 | Did not reject | `500` |

4 requests to an API on another origin. A full mug means the text names the cause.

## Find which cause you have

### Open the browser console

`fetch()` rejects with the same `TypeError: Failed to fetch` for every network failure. The console line beside it names the real cause.

### The API answered without a CORS header

The console says `blocked by CORS policy`. The server did answer, but the page's origin is not allowed to read the response, so the browser throws the answer away.

Output

```text
Access to fetch at 'http://127.0.0.1:4874/api/closed' from origin 'http://127.0.0.1:4873' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
```

### Nothing listens on that host and port

The console says `net::ERR_CONNECTION_REFUSED`. The API is not running, or the port in the URL is wrong. Start it, then check the port.

Output

```text
Failed to load resource: net::ERR_CONNECTION_REFUSED
```

### The host name does not resolve

The console says `net::ERR_NAME_NOT_RESOLVED`. DNS has no record for the host. Check the hostname for a typo, and the environment variable that holds the API URL on this deploy.

Output

```text
Failed to load resource: net::ERR_NAME_NOT_RESOLVED
```

## Fix it in your code

### Send the CORS header from the API

Answer with `Access-Control-Allow-Origin` set to your page's origin, or `*` for a public API. In our test the same endpoint went from `Failed to fetch` to `HTTP 200` with only that header added.

```bash
Access-Control-Allow-Origin: https://app.example.com
```

### Check the status, because a 500 does not reject

`fetch()` resolves on any HTTP answer, including 404 and 500. In our test a 500 with the body `{"error":"tap jammed"}` reached the `then` branch, not the `catch`. Test `response.ok` before you read the body.

```bash
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP ${response.status} for ${url}`);
```

### Log the URL with the error

A rejected `fetch()` has no response, and its stack points at your own code, not at the cause. Catch it where you call `fetch()` and keep the method and URL with the error, so your error tracking shows which request failed.

```bash
try {
  return await fetch(url);
} catch (error) {
  console.error("fetch failed", url, error);
  throw error;
}
```

## What we saw when we tested it

The page ran at `http://127.0.0.1:4873` in Chromium 152 with `@logbrew/browser` 0.1.21 and its fetch instrumentation installed. An API at `http://127.0.0.1:4874` answered 3 paths, and we sent 5 requests with no `catch`, so each rejection reached the SDK as an unhandled rejection.

`/api/closed` answered 200 without a CORS header, and the request rejected with `TypeError: Failed to fetch`. A request to port 4875, where nothing listened, and one to `http://keg.invalid/api` rejected with the same error. In all 3 cases `error.message` was `Failed to fetch`, `error.name` was `TypeError`, and the stack pointed at our own `fetch()` call.

The console told them apart. The first said `blocked by CORS policy`, the second `net::ERR_CONNECTION_REFUSED`, the third `net::ERR_NAME_NOT_RESOLVED`. `/api/broken`, which answered 500 with the header, did not reject at all, and `/api/open`, which answered 200 with the header, gave `HTTP 200 {"ok":true}`.

## Why every cause has the same message

The Fetch Standard turns every failure before a response into 1 thing, a network error, which is a response with type `error` and status 0. A CORS failure is one too. In `cors` mode, a resource that does not understand the CORS protocol gives a network error.

The `fetch()` method rejects its promise with a `TypeError` for a network error, and for nothing else. MDN puts it the same way. The promise rejects only when the request fails, for example on a badly formed URL or a network error, and not on an HTTP status like 404 or 504.

MDN's page on CORS errors says the specifics of a failed CORS request are not available to JavaScript for security reasons, and that the console is the only place to find them. whatwg/fetch#526 has asked for more informative error types since 2017 and is still open.

## What LogBrew records

Each rejection arrived as 1 issue named `Unhandled promise rejection: TypeError`, with stack frames into our bundle and the grouping key `browser.unhandledrejection:TypeError:/app.js`. That tells you where you called `fetch()`, not what failed.

The fetch instrumentation added a span in the same trace, `browser.fetch GET /api/closed`, with status `error`, the method, the request path, and `errorType` `TypeError`. The span names the request that failed even though the error does not.

The 500 answer produced no issue, only a span with status `error` and `statusCode` 500. The 200 answer produced a span with status `ok`. So in LogBrew a 500 and a network failure are 2 different spans, while in your code only the second one reaches `catch`.

## Questions people ask

### What does TypeError Failed to fetch mean?

The browser could not get an HTTP response for a `fetch()` call. The server was unreachable, the host did not resolve, or CORS blocked the response. The message is the same in all 3 cases.

### Is Failed to fetch always a CORS error?

No. In our test a missing CORS header, a port with no server, and a host with no DNS record all gave this message. Only the console line beside it names the cause.

### Why does fetch not reject on a 404 or 500?

The Fetch Standard rejects only for a network error. An HTTP answer with any status is a response, so `fetch()` resolves and you test `response.ok` yourself.

### How do I catch Failed to fetch in JavaScript?

Wrap the call in `try` and `catch`, or add `.catch()` to the promise. The error is a `TypeError` with no response, so log the URL and method yourself.

### Does Failed to fetch mean the server is down?

Sometimes. A server that is down gives `net::ERR_CONNECTION_REFUSED` in the console. The same `Failed to fetch` also comes from a missing CORS header or a host name with no DNS record.

## See which request failed, and why

The LogBrew browser SDK records each `fetch()` as a span with its method, path, and status, in the same trace as the error it raised. Start on the generous free tier, no card needed.

[Start Free](https://logbrew.co/en)

## Sources

- [MDN, Window: fetch() method](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch)
- [MDN, CORS errors](https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS/Errors)
- [Fetch Standard, The fetch() method](https://fetch.spec.whatwg.org/#fetch-method)
- [whatwg/fetch#526](https://github.com/whatwg/fetch/issues/526)

## More JavaScript error fixes

- [Fix the script error that hides its message, file, and line](https://logbrew.co/en/errors/script-error)
- [JavaScript errors we reproduced, and how to fix each one](https://logbrew.co/en/errors)
