Workers のエラーと例外を確認します。
本番で動いている Worker に、レスポンスを返せないエラーがあると、クライアントは次のエラーコード付きのエラーページを受け取ります。
| エラーコード | 意味 |
|---|---|
1101 |
Worker が JavaScript 例外をスローしました。 |
1102 |
Worker が CPU 時間制限 を超えました。 |
1103 |
この Worker の所有者は Cloudflare Support に問い合わせる必要があります |
1019 |
Worker が ループ制限 に達しました。 |
1021 |
Worker がアクセスできないホストをリクエストしました。 |
1022 |
Cloudflare がリクエストを Worker にルーティングできませんでした。 |
1024 |
Worker は Cloudflare 所有の IP アドレスへサブリクエストを送れません。 |
1027 |
Worker が Free プランの 1 日あたりのリクエスト上限 を超えました。 |
1042 |
Worker が同じゾーン上の別の Worker へ fetch しようとしました。これは global_fetch_strictly_public compatibility flag を使う場合にのみ 対応 しています。 |
10162 |
モジュールの Content-Type が非対応です。 |
その他の 11xx エラーは、多くの場合 Workers ランタイム自体の問題を示します。エラーが発生している場合は ステータスページ ↗ を確認してください。
Worker は自身または別の Worker を 16 回を超えて呼び出せません。Workers 間の無限ループを防ぐため、CF-EW-Via ヘッダーの値は、残りの呼び出し回数を示す整数です。Worker が呼び出されるたびに、この整数は 1 減ります。カウントが 0 になると、1019 エラーが返されます。
一部のリクエストは、エラーメッセージに The script will never generate a response を含む 1101 エラーを返すことがあります。これは、リクエストに関連するコードがすべて実行され、イベントループにイベントが残っていないのに、Response が返されていないことを Workers ランタイムが検出した場合に発生します。
最も多い原因は、Response を返すために必要な Promise が、一度も解決(resolve)も拒否(reject)もされないことです。デバッグするときは、コードや依存関係の中で Response をブロックしている Promise を探し、解決または拒否されていることを確認します。
ブラウザや他の JavaScript ランタイムでは、同等のコードは無限にハングし、バグとメモリリークの両方につながります。Workers ランタイムはデバッグしやすいよう、明示的なエラーをスローします。
次の例では、Response が決して起きない Promise の解決に依存しています。resolve コールバックのコメントを外すと問題は解消します。
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);
},
};no-floating-promises eslint ルール ↗ を適用すると、Promise が作成されたのに適切に扱われていない場合に報告されるため、この問題を防げます。
WebSocket にサーバー側接続を閉じる適切なコードがないと、Workers ランタイムは script will never generate a response エラーをスローします。次の例では、クライアントからの 'close' イベントで server.close() を呼んでおらず、エラーになります。これを避けるには、イベントリスナーや他のサーバー側ロジックで、WebSocket のサーバー側接続を正しく閉じてください。
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,
});
}エラーメッセージ TypeError: Illegal invocation: function called with incorrect this reference は混乱しやすいです。
これは通常、this を使う関数を呼び出しているのに、this の値が失われていることが原因です。
たとえば、this に依存する obj.foo() メソッドを持つ obj がある場合、obj.foo(); として実行すると this は正しく obj を参照します。一方、メソッドを変数に代入して(例: const func = obj.foo;)、その変数を呼ぶと(例: func();)、this は undefined になります。メソッドを単独の関数として呼ぶと this が失われるためです。これは JavaScript の標準的な動作です。
実務では、this の存在に依存する関数を持つランタイム提供の JavaScript オブジェクト(ctx など)を分割代入するときに、よく見られます。
次のコードはエラーになります。
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);
},
};分割代入を避けるか、関数を元のコンテキストに再バインドすると、このエラーを防げます。
次のコードは正しく動きます。
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);
},
};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.このエラーは、ある Worker の呼び出しで作成した入出力(I/O)オブジェクト(ストリーム、Request、Response など)を、別の呼び出しのコンテキストで共有しようとしたときに発生します。
Cloudflare Workers では、各呼び出しは独立して処理され、独自の実行コンテキストを持ちます。この設計により、リクエスト同士を分離し、パフォーマンスとセキュリティを確保しています。異なる呼び出し間で I/O オブジェクトを共有すると、この分離が壊れます。これらのオブジェクトは作成元のリクエストに紐づいているため、別のリクエストのハンドラーからアクセスすることは許可されず、このエラーになります。
最も多い原因は、Request のような I/O オブジェクトをグローバルスコープにキャッシュし、後続のリクエストでアクセスすることです。たとえば、次のコードをローカル開発で実行し、Worker に短い間隔で 2 回リクエストすると、このエラーを再現できます。
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;
},
};I/O オブジェクトそのものではなく、データだけをグローバルスコープに保存すると修正できます。
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);
},
};リクエストをまたいで状態を共有する必要がある場合は、Durable Objects の利用を検討してください。リクエストをまたいでデータをキャッシュする必要がある場合は、Workers KV の利用を検討してください。
これらのエラーは、Worker のアップロードまたは変更時に発生します。
| エラーコード | 意味 |
|---|---|
10006 |
Worker のコードをパースできませんでした。 |
10007 |
Worker または workers.dev サブドメイン が見つかりません。 |
10015 |
アカウントに Workers の利用権限がありません。 |
10016 |
Worker 名が無効です。 |
10021 |
検証エラーです。詳細は 検証エラー を参照してください。 |
10026 |
リクエストボディをパースできませんでした。 |
10027 |
アップロードした Worker が Worker サイズ制限 を超えました。 |
10035 |
同じリソースを同時に複数回変更しようとしました |
10037 |
アカウントが 許可されている Workers 数 を超えました。 |
10052 |
名前のない バインディング がアップロードされました。 |
10054 |
環境変数またはシークレットが サイズ制限 を超えています。 |
10055 |
環境変数またはシークレットの数が Worker あたりの上限 を超えています。 |
10056 |
バインディング が見つかりません。 |
10068 |
アップロードした Worker に登録済みの イベントハンドラー がありません。 |
10069 |
アップロードした Worker に、Workers ランタイムが非対応の イベントハンドラー が含まれています。 |
10021 エラーコードは、Worker のデプロイ時に Cloudflare がトップレベルスコープ(ハンドラー が呼び出される前に実行されるすべて)を読み込んで実行しようとしたときに発生するエラーをまとめたものです。たとえば、SyntaxError をスローする不正な JavaScript の壊れた Worker をデプロイしようとすると、Cloudflare は Worker をデプロイしません。
具体的なエラーケースには、次のようなものがあります(これらに限りません)。
Worker のトップレベルスコープで、起動時間制限(1 秒) を超える CPU 時間を使う処理をしていることを意味します。
Worker のトップレベルスコープで、メモリ制限(128 MB) を超えるメモリを確保していることを意味します。
ランタイムエラーはランタイム内で発生し、エラーページは表示されず、エンドユーザーには見えません。ランタイムエラーはログで確認します。
| エラーメッセージ | 意味 |
|---|---|
Network connection lost |
接続失敗です。fetch またはバインディングの呼び出しをキャッチして再試行します。 |
Memory limitwould be exceededbefore EOF |
メモリ制限 を超えるストリームまたはバッファを読み込もうとしています。 |
daemonDown |
Worker の呼び出しに一時的な問題が発生しました。 |
アプリケーションがダウンタイムやエラーを返しているかを確認する手順は次のとおりです。
-
Cloudflare ダッシュボードで、Workers & Pages ページを開きます。
Workers & Pages を開く ↗ -
Overview で Worker を選び、メトリクスを確認します。
Errors by invocation status チャートは、エラー数を次のカテゴリに分けて表示します。
| エラー | 意味 |
|---|---|
Uncaught Exception |
実行中に Worker のコードが JavaScript 例外をスローしました。 |
Exceeded CPU Time Limits |
Worker が CPU 時間制限または他のリソース制約を超えました。 |
Exceeded Memory |
実行中に Worker がメモリ制限を超えました。 |
Internal |
Workers ランタイムで内部エラーが発生しました。 |
Client disconnected by type チャートは、クライアント切断エラー数を次のカテゴリに分けて表示します。
| クライアント切断 | 意味 |
|---|---|
Response Stream Disconnected |
Worker リクエストフローの遅延プロキシ段階で接続が終了しました。WebSockets のような長寿命の接続でよく見られます。 |
Cancelled |
Worker がレスポンスを完了する前に、クライアントが切断しました。 |
Workers Logs は、Workers のデバッグに使える強力なツールです。実行中に発生した未キャッチ例外を含め、Worker が生成した過去のログをすべて表示します。
Workers Logs ですべてのエラーを探すには、次のフィルターを使えます: $metadata.error EXISTS。これにより、エラーが関連付けられているログがすべて表示されます。$workers.outcome でフィルタすると、エラーになったリクエストも探せます。たとえば $workers.outcome = "exception" で、未キャッチ例外になったリクエストをすべて探せます。
考えられる outcome の値はすべて Workers Trace Event リファレンスにあります。
wrangler で Worker をデバッグするには、wrangler tail を使って例外を確認し、修正します。
例外は、wrangler tail が返す JSON の exceptions フィールドに表示されます。エラーの原因となっている例外を特定したら、修正をデプロイし、ログの tail を続けて修正を確認します。
Worker は、パブリック Internet 上の任意の HTTP サービスへ HTTP リクエストを送れます。Sentry ↗ のようなサービスを使い、エラーを報告する HTTP リクエストを送ることで、Worker からエラーログを収集できます。どのようなリクエストを送るかは、各サービスの API ドキュメントを参照してください。
外部のログ戦略を使うときは、フローティング Promise(await も return もされず、ctx.waitUntil() にも渡されていない Promise)は、Worker の呼び出しが完了するとキャンセルされることがある点に注意してください。レスポンスボディをクライアントへストリーミングしている間は、呼び出しは完了していません。レスポンス完了後にログを実行するには、リクエストの Promise を ctx.waitUntil() に渡します。例:
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);
},
};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,
});
}Wasm Coredump Service ↗ を設定すると、Rust Workers アプリケーションからコアダンプを収集し、ログ、Sentry、R2 に保存して wasmgdb ↗ で分析できます。詳細は ブログ記事 ↗ を参照してください。
passThroughOnException() を使うと、Worker の実行中に例外がスローされた場合に、リクエストをオリジンへ転送できます。これにより、アプリケーションの機能を損なわずに、Workers でログ、トラッキング、その他の機能を追加できます。
ctx.passThroughOnException() が転送するのは、Worker コード内の未処理例外であり、オリジンの fetch() からのエラーではありません。オリジンへリクエストをプロキシするときは、fetch(request) を try...catch で囲み、失敗時は 5xx レスポンスを返します。オリジンの fetch() がリクエストボディを消費したあとにスローした場合、passThroughOnException() はボディを再送できません。
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);
},
};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);
}- Workers からログを取る - Workers のログ方法を確認します。
- Logpush - Workers Trace Event Logs を対応先へプッシュする方法を確認します。
- RPC のエラー処理 - リモートプロシージャコールからのエラーの扱い方を確認します。