---
title: Errors and exceptions · Cloudflare Workers docs
description: Review Workers errors and exceptions.
lastUpdated: 2025-04-25T19:35:18.000Z
source_url:
  html: https://zt-dark-mode-changelog.preview.developers.cloudflare.com/workers/observability/errors/index.md
  md: https://zt-dark-mode-changelog.preview.developers.cloudflare.com/workers/observability/errors/
---

Review Workers errors and exceptions.

## Error pages generated by Workers

When a Worker running in production has an error that prevents it from returning a response, the client will receive an error page with an error code, defined as follows:

| Error code | Meaning |
| - | - |
| `1101` | Worker threw a JavaScript exception. |
| `1102` | Worker exceeded [CPU time limit](https://developers.cloudflare.com/workers/platform/limits/#cpu-time). |
| `1103` | The owner of this worker needs to contact [Cloudflare Support](https://developers.cloudflare.com/support/contacting-cloudflare-support/) |
| `1015` | Worker hit the [burst rate limit](https://developers.cloudflare.com/workers/platform/limits/#burst-rate). |
| `1019` | Worker hit [loop limit](#loop-limit). |
| `1021` | Worker has requested a host it cannot access. |
| `1022` | Cloudflare has failed to route the request to the Worker. |
| `1024` | Worker cannot make a subrequest to a Cloudflare-owned IP address. |
| `1027` | Worker exceeded free tier [daily request limit](https://developers.cloudflare.com/workers/platform/limits/#daily-request). |
| `1042` | Worker tried to fetch from another Worker on the same zone, which is [unsupported](https://developers.cloudflare.com/workers/runtime-apis/fetch/). |

Other `11xx` errors generally indicate a problem with the Workers runtime itself. Refer to the [status page](https://www.cloudflarestatus.com) if you are experiencing an error.

### Loop limit

A Worker cannot call itself or another Worker more than 16 times. In order to prevent infinite loops between Workers, the [`CF-EW-Via`](https://developers.cloudflare.com/fundamentals/reference/http-headers/#cf-ew-via) header's value is an integer that indicates how many invocations are left. Every time a Worker is invoked, the integer will decrement by 1. If the count reaches zero, a [`1019`](#error-pages-generated-by-workers) error is returned.

### "The script will never generate a response" errors

Some requests may return a 1101 error with `The script will never generate a response` in the error message. This occurs when the Workers runtime detects that all the code associated with the request has executed and no events are left in the event loop, but a Response has not been returned.

#### Cause 1: Unresolved Promises

This is most commonly caused by relying on a Promise that is never resolved or rejected, which is required to return a Response. To debug, look for Promises within your code or dependencies' code that block a Response, and ensure they are resolved or rejected.

In browsers and other JavaScript runtimes, equivalent code will hang indefinitely, leading to both bugs and memory leaks. The Workers runtime throws an explicit error to help you debug.

In the example below, the Response relies on a Promise resolution that never happens. Uncommenting the `resolve` callback solves the issue.

```js
export default {
  fetch(req) {
    let response = new Response("Example response");
    let { promise, resolve } = Promise.withResolvers();


    // If the promise is not resolved, the Workers runtime will
    // recognize this and throw an error.


    // setTimeout(resolve, 0)


    return promise.then(() => response);
  },
};
```

You can prevent this by enforcing the [`no-floating-promises` eslint rule](https://typescript-eslint.io/rules/no-floating-promises/), which reports when a Promise is created and not properly handled.

#### Cause 2: WebSocket connections that are never closed

If a WebSocket is missing the proper code to close its server-side connection, the Workers runtime will throw a `script will never generate a response` error. In the example below, the `'close'` event from the client is not properly handled by calling `server.close()`, and the error is thrown. In order to avoid this, ensure that the WebSocket's server-side connection is properly closed via an event listener or other server-side logic.

```js
async function handleRequest(request) {
  let webSocketPair = new WebSocketPair();
  let [client, server] = Object.values(webSocketPair);
  server.accept();


  server.addEventListener("close", () => {
    // This missing line would keep a WebSocket connection open indefinitely
    // and results in "The script will never generate a response" errors
    // server.close();
  });


  return new Response(null, {
    status: 101,
    webSocket: client,
  });
}
```

### "Illegal invocation" errors

The error message `TypeError: Illegal invocation: function called with incorrect this reference` can be a source of confusion.

This is typically caused by calling a function that calls `this`, but the value of `this` has been lost.

For example, given an `obj` object with the `obj.foo()` method which logic relies on `this`, executing the method via `obj.foo();` will make sure that `this` properly references the `obj` object. However, assigning the method to a variable, e.g.`const func = obj.foo;` and calling such variable, e.g. `func();` would result in `this` being `undefined`. This is because `this` is lost when the method is called as a standalone function. This is standard behavior in JavaScript.

In practice, this is often seen when destructuring runtime provided Javascript objects that have functions that rely on the presence of `this`, such as `ctx`.

The following code will error:

```js
export default {
  async fetch(request, env, ctx) {
    // destructuring ctx makes waitUntil lose its 'this' reference
    const { waitUntil } = ctx;
    // waitUntil errors, as it has no 'this'
    waitUntil(somePromise);


    return fetch(request);
  },
};
```

Avoid destructuring or re-bind the function to the original context to avoid the error.

The following code will run properly:

```js
export default {
  async fetch(request, env, ctx) {
    // directly calling the method on ctx avoids the error
    ctx.waitUntil(somePromise);


    // alternatively re-binding to ctx via apply, call, or bind avoids the error
    const { waitUntil } = ctx;
    waitUntil.apply(ctx, [somePromise]);
    waitUntil.call(ctx, somePromise);
    const reboundWaitUntil = waitUntil.bind(ctx);
    reboundWaitUntil(somePromise);


    return fetch(request);
  },
};
```

### Cannot perform I/O on behalf of a different request

```plaintext
Uncaught (in promise) Error: Cannot perform I/O on behalf of a different request. I/O objects (such as streams, request/response bodies, and others) created in the context of one request handler cannot be accessed from a different request's handler.
```

This error occurs when you attempt to share input/output (I/O) objects (such as streams, requests, or responses) created by one invocation of your Worker in the context of a different invocation.

In Cloudflare Workers, each invocation is handled independently and has its own execution context. This design ensures optimal performance and security by isolating requests from one another. When you try to share I/O objects between different invocations, you break this isolation. Since these objects are tied to the specific request they were created in, accessing them from another request's handler is not allowed and leads to the error.

This error is most commonly caused by attempting to cache an I/O object, like a [Request](https://developers.cloudflare.com/workers/runtime-apis/request/) in global scope, and then access it in a subsequent request. For example, if you create a Worker and run the following code in local development, and make two requests to your Worker in quick succession, you can reproduce this error:

```js
let cachedResponse = null;


export default {
  async fetch(request, env, ctx) {
    if (cachedResponse) {
      return cachedResponse;
    }
    cachedResponse = new Response("Hello, world!");
    await new Promise((resolve) => setTimeout(resolve, 5000)); // Sleep for 5s to demonstrate this particular error case
    return cachedResponse;
  },
};
```

You can fix this by instead storing only the data in global scope, rather than the I/O object itself:

```js
let cachedData = null;


export default {
  async fetch(request, env, ctx) {
    if (cachedData) {
      return new Response(cachedData);
    }
    const response = new Response("Hello, world!");
    cachedData = await response.text();
    return new Response(cachedData, response);
  },
};
```

If you need to share state across requests, consider using [Durable Objects](https://developers.cloudflare.com/durable-objects/). If you need to cache data across requests, consider using [Workers KV](https://developers.cloudflare.com/kv/).

## Errors on Worker upload

These errors occur when a Worker is uploaded or modified.

| Error code | Meaning |
| - | - |
| `10006` | Could not parse your Worker's code. |
| `10007` | Worker or [workers.dev subdomain](https://developers.cloudflare.com/workers/configuration/routing/workers-dev/) not found. |
| `10015` | Account is not entitled to use Workers. |
| `10016` | Invalid Worker name. |
| `10021` | Validation Error. Refer to [Validation Errors](https://developers.cloudflare.com/workers/observability/errors/#validation-errors-10021) for details. |
| `10026` | Could not parse request body. |
| `10027` | Your Worker exceeded the size limit of XX MB (for more details see [Worker size limits](https://developers.cloudflare.com/workers/platform/limits/#worker-size)) |
| `10035` | Multiple attempts to modify a resource at the same time |
| `10037` | An account has exceeded the number of [Workers allowed](https://developers.cloudflare.com/workers/platform/limits/#number-of-workers). |
| `10052` | A [binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/) is uploaded without a name. |
| `10054` | A environment variable or secret exceeds the [size limit](https://developers.cloudflare.com/workers/platform/limits/#environment-variables). |
| `10055` | The number of environment variables or secrets exceeds the [limit/Worker](https://developers.cloudflare.com/workers/platform/limits/#environment-variables). |
| `10056` | [Binding](https://developers.cloudflare.com/workers/runtime-apis/bindings/) not found. |
| `10068` | The uploaded Worker has no registered [event handlers](https://developers.cloudflare.com/workers/runtime-apis/handlers/). |
| `10069` | The uploaded Worker contains [event handlers](https://developers.cloudflare.com/workers/runtime-apis/handlers/) unsupported by the Workers runtime. |

### Validation Errors (10021)

The 10021 error code includes all errors that occur when you attempt to deploy a Worker, and Cloudflare then attempts to load and run the top-level scope (everything that happens before your Worker's [handler](https://developers.cloudflare.com/workers/runtime-apis/handlers/) is invoked). For example, if you attempt to deploy a broken Worker with invalid JavaScript that would throw a `SyntaxError` — Cloudflare will not deploy your Worker.

Specific error cases include but are not limited to:

#### Worker exceeded the upload size limit

A Worker can be up to 10 MB in size after compression on the Workers Paid plan, and up to 3 MB on the Workers Free plan.

To reduce the upload size of a Worker, you should consider removing unnecessary dependencies and/or using Workers KV, a D1 database or R2 to store configuration files, static assets and binary data instead of attempting to bundle them within your Worker code.

Another method to reduce a Worker's file size is to split its functionality across multiple Workers and connect them using [Service bindings](https://developers.cloudflare.com/workers/runtime-apis/bindings/service-bindings/).

#### Script startup exceeded CPU time limit

This means that you are doing work in the top-level scope of your Worker that takes [more than the startup time limit (400ms)](https://developers.cloudflare.com/workers/platform/limits/#worker-startup-time) of CPU time.

This is usually a sign of a bug and/or large performance problem with your code or a dependency you rely on. It's not typical to use more than 400ms of CPU time when your app starts. The more time your Worker's code spends parsing and executing top-level scope, the slower your Worker will be when you deploy a code change or a new [isolate](https://developers.cloudflare.com/workers/reference/how-workers-works/) is created.

This error is most commonly caused by attempting to perform expernsive initialization work directly in top level (global) scope, rather than either at build time or when your Worker's handler is invoked. For example, attempting to initialize an app by generating or consuming a large schema.

To analyze what is consuming so much CPU time, you should open Chrome DevTools for your Worker and look at the Profiling and/or Performance panels to understand where time is being spent. Is there something glaring that consumes tons of CPU time, especially the first time you make a request to your Worker?

## Runtime errors

Runtime errors will occur within the runtime, do not throw up an error page, and are not visible to the end user. Runtime errors are detected by the user with logs.

| Error message | Meaning |
| - | - |
| `Network connection lost` | Connection failure. Catch a `fetch` or binding invocation and retry it. |
| `Memory limit` `would be exceeded` `before EOF` | Trying to read a stream or buffer that would take you over the [memory limit](https://developers.cloudflare.com/workers/platform/limits/#memory). |
| `daemonDown` | A temporary problem invoking the Worker. |

## Identify errors: Workers Metrics

To review whether your application is experiencing any downtime or returning any errors:

1. Log in to the [Cloudflare dashboard](https://dash.cloudflare.com) and select your account.
2. In **Account Home**, select **Workers & Pages**.
3. In **Overview**, select your Worker and review your Worker's metrics.

### Worker Errors

The **Errors by invocation status** chart shows the number of errors broken down into the following categories:

| Error | Meaning |
| - | - |
| `Uncaught Exception` | Your Worker code threw a JavaScript exception during execution. |
| `Exceeded CPU Time Limits` | Worker exceeded CPU time limit or other resource constraints. |
| `Exceeded Memory` | Worker exceeded the memory limit during execution. |
| `Internal` | An internal error occurred in the Workers runtime. |

The **Client disconnected by type** chart shows the number of client disconnect errors broken down into the following categories:

| Client Disconnects | Meaning |
| - | - |
| `Response Stream Disconnected` | Connection was terminated during the deferred proxying stage of a Worker request flow. It commonly appears for longer lived connections such as [WebSockets](https://developers.cloudflare.com/workers/runtime-apis/websockets/). |
| `Cancelled` | The Client disconnected before the Worker completed its response. |

## Debug exceptions with Workers Logs

[Workers Logs](https://developers.cloudflare.com/workers/observability/logs/workers-logs) is a powerful tool for debugging your Workers. It shows all the historic logs generated by your Worker, including any uncaught exceptions that occur during execution.

To find all your errors in Workers Logs, you can use the following filter: `$metadata.error EXISTS`. This will show all the logs that have an error associated with them. You can also filter by `$workers.outcome` to find the requests that resulted in an error. For example, you can filter by `$workers.outcome = "exception"` to find all the requests that resulted in an uncaught exception.

All the possible outcome values can be found in the [Workers Trace Event](https://developers.cloudflare.com/logs/reference/log-fields/account/workers_trace_events/#outcome) reference.

## Debug exceptions from `Wrangler`

To debug your worker via wrangler use `wrangler tail` to inspect and fix the exceptions.

Exceptions will show up under the `exceptions` field in the JSON returned by `wrangler tail`. After you have identified the exception that is causing errors, redeploy your code with a fix, and continue tailing the logs to confirm that it is fixed.

## Set up a 3rd party logging service

A Worker can make HTTP requests to any HTTP service on the public Internet. You can use a service like [Sentry](https://sentry.io) to collect error logs from your Worker, by making an HTTP request to the service to report the error. Refer to your service’s API documentation for details on what kind of request to make.

When using an external logging strategy, remember that outstanding asynchronous tasks are canceled as soon as a Worker finishes sending its main response body to the client. To ensure that a logging subrequest completes, pass the request promise to [`event.waitUntil()`](https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent/waitUntil). For example:

* Module Worker

  ```js
  export default {
    async fetch(request, env, ctx) {
      function postLog(data) {
        return fetch("https://log-service.example.com/", {
          method: "POST",
          body: data,
        });
      }


      // Without ctx.waitUntil(), the `postLog` function may or may not complete.
      ctx.waitUntil(postLog(stack));
      return fetch(request);
    },
  };
  ```

* Service Worker

  ```js
  addEventListener("fetch", (event) => {
    event.respondWith(handleEvent(event));
  });


  async function handleEvent(event) {
    // ...


    // Without event.waitUntil(), the `postLog` function may or may not complete.
    event.waitUntil(postLog(stack));
    return fetch(event.request);
  }


  function postLog(data) {
    return fetch("https://log-service.example.com/", {
      method: "POST",
      body: data,
    });
  }
  ```

## Go to origin on error

By using [`event.passThroughOnException`](https://developers.cloudflare.com/workers/runtime-apis/context/#passthroughonexception), a Workers application will forward requests to your origin if an exception is thrown during the Worker's execution. This allows you to add logging, tracking, or other features with Workers, without degrading your application's functionality.

* Module Worker

  ```js
  export default {
    async fetch(request, env, ctx) {
      ctx.passThroughOnException();
      // an error here will return the origin response, as if the Worker wasn't present
      return fetch(request);
    },
  };
  ```

* Service Worker

  ```js
  addEventListener("fetch", (event) => {
    event.passThroughOnException();
    event.respondWith(handleRequest(event.request));
  });


  async function handleRequest(request) {
    // An error here will return the origin response, as if the Worker wasn’t present.
    // ...
    return fetch(request);
  }
  ```

## Related resources

* [Log from Workers](https://developers.cloudflare.com/workers/observability/logs/) - Learn how to log your Workers.
* [Logpush](https://developers.cloudflare.com/workers/observability/logs/logpush/) - Learn how to push Workers Trace Event Logs to supported destinations.
* [RPC error handling](https://developers.cloudflare.com/workers/runtime-apis/rpc/error-handling/) - Learn how to handle errors from remote-procedure calls.
