- Ошибки запросов к API — HTTP-ответ на синхронный вызов API (аутентификация, оплата, некорректный запрос, отсутствующий ресурс). См. Ошибки запросов к API.
- Коды сбоев prediction — запрос принят и поставлен в очередь, но сам prediction завершился со
status: "failed". Сбой описывается объектомerrorвнутри prediction, который вы получаете от эндпоинтов статуса prediction, в доставках webhook и от эндпоинта результата. См. Коды сбоев prediction.
Коды сбоев prediction
Prediction, завершившийся сбоем, содержит объектerror:
Сбойные prediction не тарифицируются; кредиты, зарезервированные под этот запрос, освобождаются.
Prediction, который не завершился сбоем, содержит
error: null. См. Примечание о миграции, если вы делали интеграцию до 17 августа 2026 года.
Где вы получаете ошибку
Один и тот же объектerror публикуется во всех каналах, поэтому читать его можно там, куда вы и так смотрите:
Чтение сбоя из эндпоинта результата
Запрос вывода у prediction, завершившегося сбоем, возвращает400 с тем самым сбоем, который к этому привёл, под кодом уровня запроса PREDICTION_FAILED:
error.codeравенPREDICTION_FAILED— это ошибка запроса к API, означающая «prediction, вывод которого вы запросили, его не произвёл»;error.details— это собственный объектerrorэтого prediction, идентичный тому, что по тому же запросу сообщает/status, поэтому два эндпоинта никогда не могут разойтись в причине сбоя. Ветвитесь поerror.details.reasonиerror.details.retryable.
error.message повторяет сообщение prediction, так что даже клиент, читающий только сообщение верхнего уровня, получает что-то полезное.
Два timestamp, два смысла. timestamp верхнего уровня — это момент формирования данного HTTP-ответа; error.details.timestamp — момент сбоя prediction. Для prediction, который вы запрашиваете спустя дни, они разойдутся на дни. Когда речь о сбое, читайте внутренний.
Официальные клиентские библиотеки распаковывают это за вас: result() выбрасывает ошибку, у которой code, reason и retryable — собственные значения prediction, те же, что subscribe() выбрасывает для того же сбоя.
Prediction, который всё ещё в очереди или выполняется, а также отменённый, по-прежнему возвращает тот же общий 400, что и раньше.
Как решить, повторять ли запрос
Смотрите наretryable. Это поле отвечает ровно на один вопрос — даст ли повторная отправка точно такого же запроса другой результат? — и не зависит от code: один и тот же code в одном сбое может допускать повтор, а в другом — нет.
retryable необязательное. Когда оно отсутствует, используйте значение по умолчанию для соответствующего code из таблицы ниже. Именно так Sunra вёл себя до появления этого поля, поэтому откат к умолчанию всегда безопасен — он просто менее точен.
code
reason
reason называет конкретную причину, стоящую за code. Используйте его для метрик, маршрутизации и диагностики в поддержке; решение о повторе принимайте по retryable.
У каждого опубликованного сегодня reason ниже есть собственный раздел, и его якорь — сам reason: #input_fetch_failed, #moderation_blocked и так далее, — поэтому из отчёта об ошибке можно сослаться сразу на значение.
input_validation_failed
code: invalid_input · retryable: false
Запрос не прошёл собственную валидацию схемы или параметров в Sunra. message называет проблемное поле.
Что делать: исправьте названное поле. Тот же запрос будет падать и дальше.
provider_rejected_input
code: invalid_input · retryable: false
Провайдер модели отклонил один или несколько входных параметров. Если провайдер сообщает, какие именно, это отражается в message; некоторые провайдеры сообщают лишь о том, что входные данные неприемлемы, — и тогда мы так и пишем, вместо того чтобы гадать.
Что делать: сверьте свои параметры со схемой модели — значение вне диапазона, неподдерживаемое сочетание, соотношение сторон или длительность, которые модель не принимает.
input_fetch_failed
code: invalid_input · retryable: false или true
Не удалось загрузить входной файл, указанный по URL. Это единственный reason, у которого retryable действительно меняется, поэтому читайте поле, а не додумывайте:
false— хост нам отказал:4xx, адрес, с которого нам не разрешено загружать, редирект или файл сверх лимита размера;true— хост был кратковременно недоступен:5xx, таймаут или ошибка DNS.
message возвращается отправленный вами URL, чтобы вы поняли, какой именно вход не загрузился, — но без query string, поэтому учётные данные из presigned URL никогда не отражаются обратно к вам:
retryable равен false, проверьте, доступен ли URL публично и не истёк ли срок presigned-ссылки. Когда true — повторите запрос.
moderation_blocked
code: unsafe_content · retryable: false
Заблокировано системой контентной безопасности провайдера модели — это может быть как входящий промпт и медиа, так и сгенерированный результат.
Что делать: измените промпт или медиафайл. Повторная отправка того же содержимого снова будет заблокирована.
provider_rate_limited
code: service_provider_error · retryable: true
Провайдер модели ограничивает частоту запросов.
Что делать: повторите с экспоненциальной задержкой или направьте запрос на другую модель.
provider_unavailable
code: service_provider_error · retryable: true
Провайдер модели не смог обслужить запрос.
Что делать: повторите позже или направьте запрос на другую модель.
provider_timeout
code: task_timeout · retryable: true
Prediction не завершился за отведённое время.
Что делать: повторите — период меньшей нагрузки или запрос поменьше (короче длительность, ниже разрешение) повышают шансы.
provider_account_error
code: internal_server_error · retryable: false
Проблема с нашей собственной учётной записью у провайдера модели — оплата, учётные данные или постоянная квота. Это наша вина, а не проблема ваших входных данных.
Что делать: с вашей стороны ничего; повтор не поможет, а оповещение мы получаем автоматически. Направьте запрос на другую модель, если мощности нужны прямо сейчас.
endpoint_misconfigured
code: internal_server_error · retryable: false
Этот эндпоинт модели неверно настроен на нашей стороне.
Что делать: с вашей стороны ничего; повтор не поможет, а оповещение мы получаем автоматически. Если вопрос срочный, обратитесь в поддержку и укажите request_id.
queue_enqueue_failed
code: internal_server_error · retryable: true
Не удалось поставить prediction в очередь.
Что делать: отправьте запрос повторно.
reaped_stalled
code: internal_server_error · retryable: true
Prediction завис и был принудительно завершён.
Что делать: отправьте запрос повторно.
Неизвестные значения
Иcode, и reason являются открытыми множествами. По мере того как мы классифицируем всё больше сбоев, новые значения добавляются без объявления breaking change. Ваша интеграция не должна падать, терять ошибку или отвергать payload, встретив незнакомое значение.
- Неизвестный
reason— считайте, чтоreasonотсутствует, и принимайте решение поretryable(или по умолчанию дляcode). Сохраните исходное значение в логах: это самый быстрый способ для поддержки опознать сбой. - Неизвестный
code— считайте егоinternal_server_error. Одно служебное значение стоит знать по имени:unknown_error_code— его Sunra отдаёт, когда prediction завершился сбоем, но восстановить для него какую-либо классификацию не удалось.
Примечание о миграции: error равен null, когда ошибки нет
Действует с 17 августа 2026 года. У объекта error одно и то же представление во всех каналах. Три различия между ними исчезли:
errorравенnull, если prediction не завершился сбоем.GET /v1/predictions/{prediction_id}раньше отвечал пустым объектом —"error": {}— для каждого успешного, стоящего в очереди или отменённого prediction. Теперь он отвечает"error": null, как это уже делает эндпоинт статуса очереди. Если вы проверяете объект на пустоту (Object.keys(response.error).length === 0), замените эту проверку на проверку на null (response.error === null).- Сбой всегда несёт непустые
codeиmessage. Там, где для сбоя было записано нечто, что мы не можем классифицировать, вы теперь получаете служебное значениеunknown_error_codeи общее сообщение — вместо поля, которое отсутствует, пусто или не является строкой. - Сбои, записанные простым текстом, доходят до вас текстом. Небольшое число prediction за апрель 2026 года сохранило свою ошибку в виде обычной строки.
GET /v1/predictions/{prediction_id}раньше её отбрасывал, а эндпоинт статуса очереди подменял её служебным сообщением; теперь оба публикуют её какmessageподcode: "unknown_error_code".
error и раньше присутствовал в каждом из этих ответов — изменилось только его значение. Доставки webhook не затронуты: именно к их форме сошлись остальные каналы, — и error по-прежнему отсутствует в доставке succeeded, а не отправляется как null.
Окно совместимости. Периода двойной выдачи нет: с этой даты API перестал отдавать "error": {}. Если вы воспроизводите или повторно обрабатываете payload, собранные до неё, считайте null и {} одним и тем же — пока эти сохранённые данные не выйдут из обращения.
Предстоящее изменение: часть сбоев получит более точный code
Сегодня значительная доля сбоев сообщается как service_provider_error, включая многие, которые не являются ни временными, ни виной провайдера. По мере того как мы классифицируем провайдеров одного за другим, такие сбои переходят к тому code, который действительно их описывает:
- детерминированный отказ провайдера принять ваши входные данные становится
invalid_input(ранееservice_provider_error); - проблема на стороне Sunra, например неверно настроенный эндпоинт или наша учётная запись у провайдера, становится
internal_server_error(ранееservice_provider_error); - входной файл, который не удалось загрузить, становится
invalid_input(ранееinternal_server_error).
code не вводится — пять значений выше остаются полным набором классифицированных кодов. Меняется лишь то, какой из них получает конкретный сбой, и меняется постепенно, провайдер за провайдером. Если ваш код ветвится по code, сейчас удачный момент перевести эту логику на retryable и reason: они описывают сбой напрямую и не затрагиваются переклассификацией.