Errors and exceptions
Last updated Oct 15, 2026 Review Workers errors and exceptions.
Enable source maps so captured JavaScript and TypeScript exception stacks point to the original files and lines. Framework builds must generate maps as well as upload them.
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. |
1103 |
The owner of this worker needs to contact Cloudflare Support |
1019 |
Worker hit 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. |
1042 |
Worker tried to fetch from another Worker on the same zone, which is only supported when the global_fetch_strictly_public compatibility flag is used. Also returned for a workers.dev URL with no Worker serving it, such as a Worker with its workers.dev route disabled. |
10162 |
Module has an unsupported Content-Type. |
Other 11xx errors generally indicate a problem with the Workers runtime itself. Refer to the status page ↗︎ 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 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 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.
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 ↗︎, 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.
Note
With the web_socket_auto_reply_to_close compatibility flag (enabled by default on compatibility dates on or after 2026-04-07), the runtime automatically completes the WebSocket close handshake. This specific error scenario is less likely to occur because the runtime handles the close for you. The example below applies to Workers on older compatibility dates.
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:
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:
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
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 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:
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:
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. If you need to cache data across requests, consider using Workers 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 not found. |
10015 |
Account is not entitled to use Workers. |
10016 |
Invalid Worker name. |
10021 |
Validation Error. Refer to Validation Errors for details. |
10026 |
Could not parse request body. |
10027 |
The uploaded Worker exceeded the Worker size limits. |
10035 |
Multiple attempts to modify a resource at the same time |
10037 |
An account has exceeded the number of Workers allowed. |
10052 |
A binding is uploaded without a name. |
10054 |
A environment variable or secret exceeds the size limit. |
10055 |
The number of environment variables or secrets exceeds the limit/Worker. |
10056 |
Binding not found. |
10057 |
An inherit binding could not be resolved. |
10068 |
The uploaded Worker has no registered event handlers. |
10069 |
The uploaded Worker contains event 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 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:
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 (1s) of CPU time.
