Skip to main content
Les erreurs apparaissent à deux endroits distincts, avec deux vocabulaires distincts :
  • Erreurs de requête API — la réponse HTTP à un appel d’API synchrone (authentification, facturation, requêtes malformées, ressources introuvables). Voir Erreurs de requête API.
  • Codes d’échec de prédiction — la requête a été acceptée et mise en file d’attente, mais la prédiction elle-même s’est terminée avec status: "failed". L’échec est décrit par l’objet error porté par la prédiction, que vous obtenez auprès des points de terminaison d’état de prédiction, dans les livraisons de webhook et depuis le point de terminaison de résultat. Voir Codes d’échec de prédiction.

Codes d’échec de prédiction

Une prédiction en échec porte un objet error :
Les prédictions en échec ne sont pas facturées ; les crédits réservés pour la requête sont libérés. Une prédiction qui n’a pas échoué porte error: null. Voir Note de migration si vous avez réalisé votre intégration avant le 17 août 2026.

Où l’erreur vous parvient

Le même objet error est publié sur tous les canaux : vous pouvez donc le lire là où vous regardez déjà.

Lire un échec depuis le point de terminaison de résultat

Demander la sortie d’une prédiction qui a échoué renvoie un 400 portant l’échec qui en est la cause, sous le code de niveau requête PREDICTION_FAILED :
Deux codes, à deux niveaux, et ils ne relèvent pas du même vocabulaire :
  • error.code vaut PREDICTION_FAILED, une erreur de requête API signifiant « la prédiction dont vous avez demandé la sortie n’en a pas produit » ;
  • error.details est l’objet error propre à la prédiction — identique à ce que /status rapporte pour la même requête, de sorte que les deux points de terminaison ne peuvent jamais diverger sur la cause de l’échec. Ramifiez votre code sur error.details.reason et error.details.retryable.
error.message reprend le message de la prédiction : un client qui ne lit que le message de premier niveau obtient donc tout de même une information utile. Deux timestamps, deux significations. Le timestamp de premier niveau indique quand cette réponse HTTP a été produite ; error.details.timestamp indique quand la prédiction a échoué. Pour une prédiction que vous récupérez plusieurs jours plus tard, les deux sont séparés de plusieurs jours. Lisez celui de l’intérieur dès que vous parlez de l’échec. Les bibliothèques clientes officielles font ce dépaquetage pour vous : result() lève une erreur dont les champs code, reason et retryable sont ceux de la prédiction elle-même, identiques à ceux que subscribe() lève pour le même échec. Une prédiction encore en file d’attente ou en cours d’exécution, ou une prédiction annulée, continue de renvoyer le même 400 générique qu’auparavant.

Décider s’il faut réessayer

Lisez retryable. Ce champ répond à une seule question — soumettre exactement la même requête donnera-t-il un résultat différent ? — et il est indépendant du code : un même code peut être réessayable dans un échec et ne pas l’être dans un autre. retryable est facultatif. Lorsqu’il est absent, repliez-vous sur la valeur par défaut par code du tableau ci-dessous. C’est le comportement qu’avait Sunra avant l’existence de ce champ : ce repli est donc toujours sûr, simplement moins précis.

code

reason

reason nomme la cause précise derrière code. Utilisez-le pour vos métriques, votre routage et le diagnostic support ; utilisez retryable pour la décision de relance. Chaque reason publiée à ce jour dispose de sa propre section ci-dessous, et son ancre est la reason elle-même — #input_fetch_failed, #moderation_blocked, etc. — de sorte qu’un rapport d’erreur peut pointer directement vers sa signification.

input_validation_failed

code: invalid_input · retryable: false La requête n’a pas passé la validation de schema ou de paramètres propre à Sunra. Le message nomme le champ en cause. Que faire : corrigez le champ nommé. La même requête continuera d’échouer.

provider_rejected_input

code: invalid_input · retryable: false Le fournisseur du modèle a rejeté un ou plusieurs paramètres d’entrée. Lorsqu’il nous précise lesquels, le message le rapporte ; certains fournisseurs signalent seulement que l’entrée était inacceptable, et nous le rapportons alors tel quel plutôt que de deviner. Que faire : vérifiez vos paramètres au regard du schema du modèle — une valeur hors plage, une combinaison non prise en charge, un rapport d’aspect ou une durée que le modèle n’accepte pas.

input_fetch_failed

code: invalid_input · retryable: false ou true Un fichier d’entrée référencé par URL n’a pas pu être récupéré. C’est la seule reason dont le retryable varie réellement : lisez donc le champ plutôt que de le supposer.
  • false — l’hôte nous a refusé l’accès : un 4xx, une adresse que nous ne sommes pas autorisés à interroger, une redirection ou un fichier dépassant la limite de taille ;
  • true — l’hôte était momentanément injoignable : un 5xx, une expiration du délai ou un échec DNS.
Le message reprend l’URL que vous avez soumise afin que vous puissiez identifier l’entrée fautive — sans sa query string, de sorte que les identifiants portés par une presigned URL ne vous sont jamais renvoyés :
Que faire : lorsque retryable vaut false, vérifiez que l’URL est accessible publiquement et qu’un lien presigned n’a pas expiré. Lorsqu’il vaut true, réessayez.

moderation_blocked

code: unsafe_content · retryable: false Bloqué par le système de sécurité du contenu du fournisseur du modèle — qu’il s’agisse du prompt et des médias fournis en entrée, ou de la sortie générée en retour. Que faire : modifiez le prompt ou les médias. Renvoyer le même contenu conduira au même blocage.

provider_rate_limited

code: service_provider_error · retryable: true Le fournisseur du modèle applique une limitation de débit. Que faire : réessayez avec un backoff, ou routez la requête vers un autre modèle.

provider_unavailable

code: service_provider_error · retryable: true Le fournisseur du modèle n’a pas pu servir la requête. Que faire : réessayez plus tard, ou routez la requête vers un autre modèle.

provider_timeout

code: task_timeout · retryable: true La prédiction ne s’est pas terminée dans le temps imparti. Que faire : réessayez — une période de charge plus faible, ou une requête plus petite (durée plus courte, résolution plus basse), améliore les chances.

provider_account_error

code: internal_server_error · retryable: false Notre propre compte chez le fournisseur du modèle pose problème — facturation, identifiants ou quota permanent. Le problème vient de nous, pas de votre entrée. Que faire : rien de votre côté ; réessayer n’y changera rien et nous sommes alertés automatiquement. Routez vers un autre modèle s’il vous faut cette capacité immédiatement.

endpoint_misconfigured

code: internal_server_error · retryable: false Ce point de terminaison de modèle est mal configuré de notre côté. Que faire : rien de votre côté ; réessayer n’y changera rien et nous sommes alertés automatiquement. Contactez le support avec le request_id si c’est urgent.

queue_enqueue_failed

code: internal_server_error · retryable: true La prédiction n’a pas pu être placée dans la file d’attente. Que faire : renvoyez la requête.

reaped_stalled

code: internal_server_error · retryable: true La prédiction s’est bloquée et a été interrompue. Que faire : renvoyez la requête.

Valeurs inconnues

code et reason sont tous deux des ensembles ouverts. De nouvelles valeurs sont ajoutées à mesure que nous classons davantage d’échecs, sans annonce de changement cassant. Votre intégration ne doit ni planter, ni ignorer l’erreur, ni rejeter la charge utile lorsqu’elle rencontre une valeur qu’elle ne reconnaît pas.
  • reason inconnu — traitez-le comme si reason était absent et décidez à partir de retryable (ou de la valeur par défaut liée au code). Conservez la valeur brute dans vos journaux : c’est le moyen le plus rapide pour le support d’identifier l’échec.
  • code inconnu — traitez-le comme internal_server_error. Une valeur sentinelle mérite d’être connue par son nom : unknown_error_code, que Sunra émet lorsqu’une prédiction a échoué sans qu’aucune classification n’ait pu être retrouvée.

Note de migration : error vaut null en l’absence d’erreur

En vigueur depuis le 17 août 2026. L’objet error a une seule représentation sur tous les canaux. Trois différences entre eux ont disparu :
  • error vaut null lorsque la prédiction n’a pas échoué. GET /v1/predictions/{prediction_id} répondait auparavant par un objet vide — "error": {} — pour toute prédiction terminée avec succès, en file d’attente ou annulée. Il répond désormais "error": null, ce que le point de terminaison d’état de la file d’attente faisait déjà. Si vous testez la vacuité (Object.keys(response.error).length === 0), remplacez ce test par une vérification de nullité (response.error === null).
  • Un échec porte toujours un code et un message non vides. Lorsqu’un échec a enregistré quelque chose que nous ne savons pas classer, vous obtenez désormais la valeur sentinelle unknown_error_code et un message générique, plutôt qu’un champ manquant, vide ou qui n’est pas une chaîne.
  • Les échecs enregistrés en texte brut vous parviennent sous forme de texte. Quelques prédictions d’avril 2026 ont stocké leur erreur sous la forme d’une simple chaîne. GET /v1/predictions/{prediction_id} la supprimait, et le point de terminaison d’état de la file d’attente la remplaçait par le message sentinelle ; tous deux la publient désormais comme message sous code: "unknown_error_code".
Rien n’a été supprimé et aucun nouveau champ n’est apparu : error était déjà présent dans chacune de ces réponses, et seule sa valeur a changé. Les livraisons de webhook sont inchangées — c’est vers leur forme que les autres canaux ont convergé — et error reste absent d’une livraison succeeded plutôt qu’envoyé à null. Fenêtre de compatibilité. Il n’y a pas de période de double émission ; l’API a cessé de produire "error": {} à cette date. Si vous rejouez ou retraitez des charges utiles capturées auparavant, traitez null et {} comme équivalents jusqu’à ce que ces données stockées disparaissent.

Changement à venir : certains échecs recevront un code plus précis

Aujourd’hui, une grande partie des échecs est signalée comme service_provider_error, y compris beaucoup qui ne sont ni transitoires ni imputables au fournisseur. À mesure que nous classons les fournisseurs un par un, ces échecs migrent vers le code qui les décrit réellement :
  • un fournisseur qui rejette votre entrée de façon déterministe devient invalid_input (auparavant service_provider_error) ;
  • un problème du côté de Sunra, comme un point de terminaison mal configuré ou notre propre compte chez le fournisseur, devient internal_server_error (auparavant service_provider_error) ;
  • un fichier d’entrée que nous n’avons pas pu récupérer devient invalid_input (auparavant internal_server_error).
Aucun code n’est renommé ni supprimé, et aucune nouvelle valeur de code n’est introduite — les cinq valeurs ci-dessus restent l’ensemble complet des codes classés. Ce qui change, c’est celui qu’un échec donné reçoit, et ce changement est progressif, fournisseur par fournisseur. Si votre code se ramifie sur code, c’est le bon moment pour déplacer cette logique vers retryable et reason, qui décrivent directement l’échec et ne sont pas affectés par cette reclassification.

Erreurs de requête API