← Cloudflare Workers / workers / observability
Ошибки и исключения
Просмотрите ошибки и исключения Workers.
Страницы ошибок, создаваемые Workers
Если в Worker, работающем в продакшене, возникает ошибка, которая не позволяет вернуть ответ, клиент получает страницу ошибки с кодом ошибки, определенным ниже:
| Код ошибки | Значение |
|---|---|
1101 |
Worker выбросил исключение JavaScript. |
1102 |
Worker превысил Лимит времени CPU. |
1103 |
Владельцу этого Worker необходимо связаться с Служба поддержки Cloudflare |
1019 |
Worker достиг лимит цикла. |
1021 |
Worker запросил хост, к которому у него нет доступа. |
1022 |
Cloudflare не смогла направить запрос в Worker. |
1024 |
Worker не может выполнить подзапрос на IP адрес, принадлежащий Cloudflare. |
1027 |
Worker превысил лимит тарифа Free дневной лимит запросов. |
1042 |
Worker попытался выполнить запрос к другому Worker в той же зоне, что возможно только поддерживается когда global_fetch_strictly_public флаг совместимости используется. |
10162 |
У модуля неподдерживаемый Content-Type. |
Другие 11xx ошибки обычно указывают на проблему в самой среде выполнения Workers. См. страница статуса ↗ если вы столкнулись с ошибкой.
Лимит цикла
Worker не может вызывать сам себя или другой Worker более 16 раз. Чтобы предотвратить бесконечные циклы между Workers, CF-EW-Via заголовка представляет собой целое число, показывающее, сколько вызовов осталось. При каждом вызове Worker это число уменьшается на 1. Когда счётчик достигает нуля, 1019 возвращается ошибка.
Ошибки «The script will never generate a response»
Некоторые запросы могут возвращать ошибку 1101 с The script will never generate a response в сообщении об ошибке. Это происходит, когда среда выполнения Workers обнаруживает, что весь код, связанный с запросом, выполнен и в цикле событий не осталось событий, но Response не был возвращён.
Причина 1: незавершенные Promise
Чаще всего причина в том, что Promise, необходимый для возврата Response, никогда не переходит в состояние resolved или rejected. Чтобы найти проблему, проверьте Promise в вашем коде или коде зависимостей, которые блокируют Response, и убедитесь, что они переходят в состояние resolved или rejected.
В браузерах и других средах выполнения 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 был потерян.
Например, если дан obj объект с obj.foo() метод, логика которого опирается на this, выполняя метод через obj.foo(); гарантирует, что this правильно ссылается на obj объект. Однако присвоение метода переменной, например,const func = obj.foo; и вызова такой переменной, например func(); приведёт к this будучи undefined. Это связано с тем, что this теряется при вызове метода как отдельной функции. Это стандартное поведение JavaScript.
На практике это часто встречается при деструктуризации предоставляемых средой выполнения объектов JavaScript, методы которых зависят от наличия this, например 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.Эта ошибка возникает, когда вы пытаетесь использовать объекты ввода-вывода (I/O), такие как потоки, запросы или ответы, созданные в рамках одного вызова Worker, в контексте другого вызова.
В Cloudflare Workers каждый вызов обрабатывается независимо и имеет собственный контекст выполнения. Такая архитектура обеспечивает оптимальную производительность и безопасность за счёт изоляции запросов друг от друга. Если вы пытаетесь передать объекты ввода-вывода между разными вызовами, эта изоляция нарушается. Поскольку такие объекты привязаны к конкретному запросу, в рамках которого они были созданы, обращение к ним из обработчика другого запроса запрещено и приводит к ошибке.
Чаще всего эта ошибка возникает при попытке закешировать объект ввода-вывода, например Запрос в глобальной области видимости, а затем обращаетесь к ней в следующем запросе. Например, если вы создадите Worker и запустите следующий код в локальной среде разработки, а затем быстро отправите два запроса к своему Worker, вы сможете воспроизвести эту ошибку:
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;
},
};Это можно исправить, если хранить в глобальной области видимости только данные, а не сам объект ввода-вывода:
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 |
A привязка загружен без имени. |
10054 |
Переменная окружения или секрет превышает ограничение размера. |
10055 |
Количество переменных окружения или секретов превышает лимит/Worker. |
10056 |
Привязка не найден. |
10068 |
У загруженного Worker нет зарегистрированных обработчики событий. |
10069 |
Загруженный Worker содержит обработчики событий не поддерживается средой выполнения Workers. |
Ошибки валидации (10021)
Код ошибки 10021 объединяет все ошибки, возникающие при попытке развернуть Worker, когда Cloudflare пытается загрузить и выполнить область верхнего уровня (всё, что происходит до того, как у вашего Worker обработчик вызывается). Например, если вы попытаетесь развернуть неисправный Worker с некорректным JavaScript, который выбросит SyntaxError : Cloudflare не развернёт ваш Worker.
К распространённым, но не исчерпывающим случаям ошибок относятся:
При запуске скрипта превышен лимит процессорного времени
Это означает, что выполнение кода в глобальной области видимости вашего Worker занимает больше времени, чем ограничение времени запуска (1s) процессорного времени.
При запуске скрипта превышен лимит памяти
Это означает, что код в глобальной области видимости вашего Worker выделяет больше памяти, чем лимит памяти (128 MB) памяти.
Ошибки Runtime
Ошибки Runtime возникают внутри среды выполнения, не приводят к отображению страницы ошибки и незаметны для конечного пользователя. Такие ошибки можно обнаружить только по логам.
| Сообщение об ошибке | Значение |
|---|---|
Network connection lost |
Ошибка подключения. Перехватите fetch или вызов привязки, и повторить его. |
Memory limitwould be exceededbefore EOF |
Попытка прочитать поток или буфер, которая превысит лимит памяти. |
daemonDown |
Временная проблема при вызове Worker. |
Выявление ошибок: Workers Metrics
Чтобы проверить, не простаивает ли ваше приложение и не возвращает ли оно ошибки:
-
На панели управления Cloudflare перейдите к разделу Workers & Pages страницу.
Перейдите в Workers & Pages ↗ -
В Обзор, выберите ваш Worker и просмотрите его метрики.
Ошибки Worker
Ошибки по статусу вызова диаграмма показывает количество ошибок с разбивкой по следующим категориям:
| Ошибка | Значение |
|---|---|
Uncaught Exception |
Во время выполнения код Worker выбросил исключение JavaScript. |
Exceeded CPU Time Limits |
Worker превысил лимит процессорного времени или другие ограничения по ресурсам. |
Exceeded Memory |
Worker превысил лимит памяти во время выполнения. |
Internal |
В среде выполнения Workers произошла внутренняя ошибка. |
Отключения клиента по типу диаграмма показывает количество ошибок отключения клиента с разбивкой по следующим категориям:
| Отключения клиента | Значение |
|---|---|
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
Чтобы отладить worker через wrangler, используйте wrangler tail чтобы проверить и устранить исключения.
Исключения отображаются в разделе exceptions поле в JSON, возвращаемом wrangler tail. После того как вы определили исключение, вызывающее ошибки, разверните исправленный код заново и продолжайте отслеживать логи, чтобы убедиться, что проблема устранена.
Настройка стороннего сервиса логирования
Worker может отправлять HTTP запросы к любому HTTP сервису в публичном интернете. Вы можете использовать такой сервис, как Sentry ↗ чтобы собирать логи ошибок вашего Worker, отправляя HTTP-запрос в сервис с сообщением об ошибке. Подробности о том, какой запрос нужно отправлять, смотрите в документации API вашего сервиса.
При использовании внешней стратегии логирования помните, что незавершённые Promise (Promise, которые не являются ни await, return, ни переданы в ctx.waitUntil()) может быть отменено по завершении вызова Worker. Вызов Worker не считается завершённым, пока тело ответа ещё передаётся клиенту потоком. Чтобы выполнить логирование после завершения ответа, передайте промис запроса в 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 ↗ чтобы собирать coredump из ваших приложений Rust Workers и сохранять их в логи, Sentry или R2 для анализа с помощью wasmgdb ↗. Ознакомьтесь с запись в блоге ↗ для дополнительных сведений.
Переход на origin при ошибке
Используя passThroughOnException(), приложение Workers может перенаправлять запросы на ваш источник, если во время выполнения 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 - Узнайте, как обрабатывать ошибки удалённых вызовов процедур.