Aller au contenu principal

Guides / Les codes de statut HTTP expliqués

406 Not Acceptable : ce que ça signifie et comment le corriger

Un 406 Not Acceptable signifie que le serveur ne peut pas produire une réponse qui corresponde à ce que le client a dit qu'il accepterait. La requête elle-même est correcte ; la négociation entre ce qui a été demandé et ce que le serveur est capable d'offrir a échoué, généralement sur le format, la langue, ou l'encodage de la réponse.

Ce que signifie 406 Not Acceptable

HTTP supporte la négociation de contenu via une famille d'en-têtes Accept : Accept pour le type de média de la réponse, Accept-Language pour la langue, et Accept-Encoding pour la compression. Un client peut envoyer n'importe lequel de ceux-ci pour dire « ne me donnez qu'une réponse que je peux utiliser ». Selon la RFC 9110, si le serveur ne peut pas produire une représentation que le client a indiqué qu'il accepterait, et qu'il choisit de le signaler plutôt que d'envoyer quelque chose quand même, il répond 406. En pratique, la plupart des serveurs ignorent tranquillement un en-tête Accept étroit et envoient leur réponse par défaut à la place, ce qui explique pourquoi un vrai 406 est moins courant que l'en-tête lui-même.

Comment l'erreur apparaît

Un navigateur déclenche rarement un 406 pendant des chargements de page normaux, parce que les navigateurs envoient des en-têtes Accept permissifs qui correspondent à presque tout ce qu'un serveur offre. Cela apparaît bien plus souvent depuis des clients d'API, des scripts, et des outils en ligne de commande qui fixent un en-tête Accept strict :

curl -i -H "Accept: application/xml" https://api.example.com/v1/status
HTTP/1.1 406 Not Acceptable
Content-Type: application/json

Dans cet exemple, le client n'a demandé que du XML et l'API ne peut produire que du JSON, donc le serveur décline plutôt que d'envoyer un format que le client a explicitement dit ne pas vouloir.

Ce qui provoque un 406 Not Acceptable

  • Un échec réel de négociation de contenu. Un en-tête Accept, Accept-Language, ou Accept-Encoding ne nommant que des formats que le serveur ne peut pas produire, le plus souvent un client demandant du XML à une API JSON seulement, ou une variante de langue spécifique que le serveur n'a pas.
  • Un pare-feu applicatif sur un hébergement partagé. C'est une cause réelle très courante qui n'a rien à voir avec la négociation de contenu : ModSecurity et des règles WAF similaires sur des environnements d'hébergement partagé bloquent les requêtes dont l'en-tête Accept paraît inhabituel, manquant, ou automatisé, et répondent 406 comme réponse de blocage indépendamment de ce qui était négocié.
  • Une API qui ne sert que du JSON, atteinte par un client envoyant Accept: text/html. Certaines API sont strictes là-dessus et refusent plutôt que de dégrader, ce qui se manifeste comme 406 pour n'importe quel client, y compris un onglet de navigateur ouvert directement sur le point de terminaison.
  • Une règle mal configurée de reverse proxy ou de CDN qui inspecte et rejette en fonction de l'en-tête Accept pour des raisons de mise en cache ou de filtrage de bots, sans rapport avec ce que le serveur d'origine peut produire.
  • Une gestion excessivement stricte d'Accept-Encoding. Un serveur configuré pour refuser toute requête qui ne liste pas une méthode de compression qu'il préfère, plutôt que de se replier sur une réponse non compressée.

Comment savoir de qui vient la faute

Si un script ou une intégration spécifique est la seule chose qui rencontre 406, vérifiez ce que disent ses en-têtes Accept, puisqu'un en-tête restreint ou mal configuré côté client en est souvent la cause directe. Si la même requête fonctionne avec un en-tête Accept simple et permissif mais échoue avec un spécifique, le serveur ne peut réellement pas servir ce format. Si le trafic normal de navigateur est aussi affecté, ou si l'erreur a commencé juste après un changement d'hébergement ou de WAF sans changement de code de votre côté, des règles de sécurité d'hébergement partagé sont le coupable le plus probable, et lancer une vérification HTTP depuis plusieurs emplacements avec les en-têtes exacts que votre intégration envoie est le moyen le plus rapide de confirmer si le blocage est constant ou spécifique à un réseau.

Comment corriger un 406 Not Acceptable

Si vous êtes visiteur

  1. Retirez ou assouplissez l'en-tête Accept dans quel que soit le script ou l'outil qui fait la requête, si vous le contrôlez, et laissez-le accepter le format par défaut que le serveur offre.
  2. Vérifiez la documentation de l'API pour savoir quels types de contenu et langues elle supporte avant de supposer que le serveur est cassé.
  3. Essayez la requête depuis un navigateur directement, puisque les navigateurs envoient des en-têtes Accept larges et rencontrent rarement cette erreur, ce qui aide à confirmer que le blocage est spécifique aux en-têtes de votre client.

Si vous gérez le site

  1. Vérifiez d'abord vos règles ModSecurity ou WAF si le 406 est inattendu et généralisé, puisque les environnements d'hébergement partagé bloquent fréquemment sur des motifs d'en-tête Accept plutôt que sur un véritable échec de négociation. Regardez les propres journaux du WAF pour l'identifiant de règle correspondant avant de toucher au code applicatif.
  2. Confirmez quels formats votre API sert réellement, et soit supportez davantage de ce que les vrais clients demandent, soit documentez clairement l'exigence pour qu'un 406 soit informatif plutôt que surprenant.
  3. Repliez-vous sur une représentation par défaut au lieu de refuser purement et simplement, là où cela est acceptable pour votre API, puisque la plupart des clients réels gèrent mieux « voici du JSON même si vous avez demandé largement » qu'un rejet pur et simple.
  4. Vérifiez les règles de reverse proxy et de CDN à la recherche de tout ce qui inspecte l'en-tête Accept pour la mise en cache ou la gestion de bots, puisqu'une règle destinée à un but peut produire un 406 comme effet secondaire pour du trafic sans rapport.

Comment prévenir qu'un 406 ne fasse tomber une intégration

Un 406 introduit par une mise à jour de sécurité d'un hébergeur ou une nouvelle règle WAF ne ressemblera pas à une panne depuis l'intérieur de votre propre réseau, puisque vos propres requêtes peuvent utiliser des en-têtes différents de ceux d'une intégration affectée. Une vérification HTTP programmée qui envoie le même en-tête Accept que vos vrais clients utilisent, avec une assertion sur le code de statut attendu, détecte un échec de négociation dès qu'il commence. Vérifier depuis plusieurs emplacements aide aussi à distinguer une règle WAF à l'échelle de l'hébergement d'une qui ne s'applique qu'à certains nœuds de bordure.

Erreurs associées

Voir 403 Forbidden pour le cas étroitement lié d'un WAF ou d'une règle de bot bloquant purement une requête plutôt que sur la négociation de contenu, l'aperçu des 4xx pour la famille plus large, et 413 Payload Too Large ailleurs dans ce lot.

Questions fréquentes

Le 406 est-il la même chose qu'une erreur CORS ?

Non. Les échecs CORS se produisent parce que le navigateur refuse d'exposer une réponse cross-origin au script appelant ; le 406 est le serveur lui-même qui décline de produire un corps de réponse du tout parce qu'il ne peut pas satisfaire le format, la langue, ou l'encodage demandé.

Pourquoi ne vois-je le 406 que depuis curl ou Postman, jamais depuis le navigateur ?

Les navigateurs envoient par défaut des en-têtes Accept larges et permissifs. Des outils comme curl n'envoient rien ou un en-tête étroit à moins que vous n'en fixiez un explicitement, ce qui est bien plus susceptible de déclencher un véritable échec de négociation ou de déclencher une règle WAF réglée pour signaler des en-têtes inhabituels.

Un 406 peut-il venir de ModSecurity même si mon en-tête Accept est parfaitement normal ?

Oui. De nombreux jeux de règles ModSecurity d'hébergement partagé signalent les requêtes comme automatisées sur la base d'une combinaison de signaux, y compris la structure et l'ordre exacts des en-têtes Accept, et répondent 406 comme réponse de blocage générique plutôt que parce que la négociation de contenu a réellement échoué.

Mon API devrait-elle renvoyer 406 ou simplement se replier sur JSON par défaut ?

Se replier sur un format raisonnable est plus convivial pour les clients réels et c'est ce que font la plupart des API en production. Renvoyer 406 se défend quand servir silencieusement le mauvais format serait activement trompeur pour l'appelant.

Quelle est la différence entre 406 et 415 ?

406 concerne ce que le client peut accepter dans la réponse. 415 Unsupported Media Type concerne ce que le serveur peut accepter dans le corps de la requête que le client a envoyée. Ils couvrent des directions opposées de la même idée de négociation.

Vérifier maintenant

Lancez la vérification gratuite sur votre propre site, sans créer de compte.

HTTP check

Surveiller en permanence

Soyez alerté dès que quelque chose casse : HostTracker vérifie depuis plus de 300 emplacements et vous prévient par e-mail, SMS, Slack, Telegram et plus encore.

Fonctionnalités HostTracker

Plus dans cette section: Les codes de statut HTTP expliqués