Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

エラーと例外

最終更新 Markdown で表示Agent セットアップ

Workers のエラーと例外を確認します。

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」エラー

一部のリクエストは、エラーメッセージに The script will never generate a response を含む 1101 エラーを返すことがあります。これは、リクエストに関連するコードがすべて実行され、イベントループにイベントが残っていないのに、Response が返されていないことを Workers ランタイムが検出した場合に発生します。

原因 1: 未解決の Promise

最も多い原因は、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 が作成されたのに適切に扱われていない場合に報告されるため、この問題を防げます。

原因 2: 閉じられない WebSocket 接続

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,
	});
}

「Illegal invocation」エラー

エラーメッセージ TypeError: Illegal invocation: function called with incorrect this reference は混乱しやすいです。

これは通常、this を使う関数を呼び出しているのに、this の値が失われていることが原因です。

たとえば、this に依存する obj.foo() メソッドを持つ obj がある場合、obj.foo(); として実行すると this は正しく obj を参照します。一方、メソッドを変数に代入して(例: const func = obj.foo;)、その変数を呼ぶと(例: func();)、thisundefined になります。メソッドを単独の関数として呼ぶと 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);
	},
};

別のリクエストの代わりに I/O を実行できない

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 アップロード時のエラー

これらのエラーは、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)

10021 エラーコードは、Worker のデプロイ時に Cloudflare がトップレベルスコープ(ハンドラー が呼び出される前に実行されるすべて)を読み込んで実行しようとしたときに発生するエラーをまとめたものです。たとえば、SyntaxError をスローする不正な JavaScript の壊れた Worker をデプロイしようとすると、Cloudflare は Worker をデプロイしません。

具体的なエラーケースには、次のようなものがあります(これらに限りません)。

Script startup exceeded CPU time limit

Worker のトップレベルスコープで、起動時間制限(1 秒) を超える CPU 時間を使う処理をしていることを意味します。

Script startup exceeded memory limit

Worker のトップレベルスコープで、メモリ制限(128 MB) を超えるメモリを確保していることを意味します。

ランタイムエラー

ランタイムエラーはランタイム内で発生し、エラーページは表示されず、エンドユーザーには見えません。ランタイムエラーはログで確認します。

エラーメッセージ 意味
Network connection lost 接続失敗です。fetch またはバインディングの呼び出しをキャッチして再試行します。
Memory limit
would be exceeded
before EOF
メモリ制限 を超えるストリームまたはバッファを読み込もうとしています。
daemonDown Worker の呼び出しに一時的な問題が発生しました。

エラーを特定する: Workers Metrics

アプリケーションがダウンタイムやエラーを返しているかを確認する手順は次のとおりです。

  1. Cloudflare ダッシュボードで、Workers & Pages ページを開きます。

    Workers & Pages を開く ↗
  2. Overview で Worker を選び、メトリクスを確認します。

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 Logs は、Workers のデバッグに使える強力なツールです。実行中に発生した未キャッチ例外を含め、Worker が生成した過去のログをすべて表示します。

Workers Logs ですべてのエラーを探すには、次のフィルターを使えます: $metadata.error EXISTS。これにより、エラーが関連付けられているログがすべて表示されます。$workers.outcome でフィルタすると、エラーになったリクエストも探せます。たとえば $workers.outcome = "exception" で、未キャッチ例外になったリクエストをすべて探せます。

考えられる outcome の値はすべて Workers Trace Event リファレンスにあります。

Wrangler から例外をデバッグする

wrangler で Worker をデバッグするには、wrangler tail を使って例外を確認し、修正します。

例外は、wrangler tail が返す JSON の exceptions フィールドに表示されます。エラーの原因となっている例外を特定したら、修正をデプロイし、ログの tail を続けて修正を確認します。

サードパーティのログサービスを設定する

Worker は、パブリック Internet 上の任意の HTTP サービスへ HTTP リクエストを送れます。Sentry のようなサービスを使い、エラーを報告する HTTP リクエストを送ることで、Worker からエラーログを収集できます。どのようなリクエストを送るかは、各サービスの API ドキュメントを参照してください。

外部のログ戦略を使うときは、フローティング Promise(awaitreturn もされず、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 コアダンプを収集して保存する

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 のエラー処理 - リモートプロシージャコールからのエラーの扱い方を確認します。

役に立ちましたか?