Unexpected token in JSON : ce que signifie l'erreur et comment la corriger

Cette erreur signifie que le texte analysé n'est pas du JSON. Le token cité indique en général ce que vous avez reçu à la place.

Vous appelez JSON.parse() ou response.json() et, au lieu des données, vous obtenez une SyntaxError. Le libellé varie selon le navigateur, mais le sens reste le même : l'analyseur a lu le texte depuis le début et il est tombé sur un caractère qui ne peut pas figurer à cet endroit dans un JSON valide. Le caractère cité et sa position sont les indices les plus précieux dont vous disposez.

La même erreur selon le moteur

Les versions récentes de Chrome et de Node.js ont changé la formulation : vous trouverez donc les deux variantes dans les résultats de recherche et dans les anciens journaux.

Où elle apparaîtMessage
Chrome, Edge, Node.js 20 et versions suivantesUnexpected token '<', "<!DOCTYPE "... is not valid JSON
Anciennes versions de Chrome, Node.js 18Unexpected token < in JSON at position 0
FirefoxJSON.parse: unexpected character at line 1 column 1 of the JSON data
SafariJSON Parse error: Unrecognized token '<'

« position 0 » ou « line 1 column 1 » signifie que le tout premier caractère était déjà incorrect. Presque toujours, cela indique que la réponse n'est pas du JSON du tout, et non qu'une petite faute de frappe s'est glissée dans un document JSON.

La cause habituelle : une page HTML au lieu du JSON

Un < inattendu en position 0 est de loin la variante la plus fréquente. Le code a demandé du JSON à une API, mais le serveur a répondu par une page HTML, et une page HTML commence par <!DOCTYPE html> ou <html>. Les raisons typiques :

  • Une URL erronée : une faute de frappe ou un préfixe /api oublié renvoie la page 404 du site.
  • Une erreur serveur : le framework affiche une page d'erreur 500 en HTML.
  • Une session expirée : la requête est redirigée vers une page de connexion, et fetch suit la redirection sans rien signaler.
  • Le fallback d'une single-page app : le serveur de développement ou l'hébergeur renvoie index.html pour tout chemin inconnu, avec un statut 200.
  • Un proxy, un CDN ou un pare-feu placé entre les deux envoie sa propre page HTML d'erreur ou de vérification.

Le moyen le plus rapide de le confirmer consiste à examiner la réponse brute avant de l'analyser :

const res = await fetch('/api/items');
console.log(res.status, res.headers.get('content-type'));
const text = await res.text();
console.log(text.slice(0, 200)); // affiche le HTML si c'est bien ce qui est revenu

Dans le navigateur, vous pouvez aussi ouvrir le panneau Réseau (Network) des outils de développement, cliquer sur la requête et consulter l'onglet Réponse (Response). Si vous y voyez du HTML, corrigez l'URL, l'authentification ou l'erreur serveur : le code d'analyse, lui, est correct.

Les autres tokens et ce qu'ils révèlent

Message actuel (ancien message)Ce que vous avez analyséCorrection
"undefined" is not valid JSON (Unexpected token u in JSON at position 0)La valeur undefined, par exemple une clé localStorage absente ou une variable non définieVérifier que la valeur existe avant de l'analyser
"[object Object]" is not valid JSON (Unexpected token o in JSON at position 1)Un objet déjà analysé, converti en chaîne par JSON.parseUtiliser l'objet directement, sans l'analyser une seconde fois
Expected property name or '}' in JSON at position 1Des guillemets simples ou des clés sans guillemets, comme dans {'a': 1} ou {a: 1}Mettre des guillemets doubles autour de chaque clé et de chaque chaîne
Expected double-quoted property name in JSON at position 8Une virgule finale, comme dans {"a": 1,}Supprimer la virgule avant l'accolade fermante
Unexpected token 'N', "{"a": NaN}" is not valid JSONNaN, Infinity ou undefined dans les donnéesLes remplacer par null ou par un nombre
Un message qui cite un token invisible ou apparemment vide en position 0Une marque d'ordre des octets (BOM) au début d'un fichier enregistré par certains éditeurs WindowsEnregistrer le fichier en UTF-8 sans BOM, ou supprimer le premier caractère

Analyser des données déjà analysées

Les bibliothèques vous livrent souvent des objets tout prêts. response.json() renvoie déjà un objet JavaScript, tout comme axios dans response.data. Passer cet objet à JSON.parse le convertit d'abord en chaîne "[object Object]", ce qui échoue en position 1. Supprimez l'analyse en trop :

const data = await res.json();
// JSON.parse(data)  <- échoue : data est déjà un objet
console.log(data.items);

Trouver l'erreur dans un vrai JSON

Quand la position indiquée se situe quelque part au milieu, le texte est bien du JSON, mais il contient une erreur. Collez-le dans le validateur JSON : il utilise le même analyseur que votre navigateur, affiche le message avec la position et la ligne, et formate le document dès qu'il est valide. La véritable erreur se trouve en général juste avant la position signalée : une virgule oubliée entre deux éléments, ou un guillemet simple là où il fallait un guillemet double.

S'en prémunir dans le code

Vérifier le statut et le type de contenu avant l'analyse transforme une erreur de syntaxe déroutante en un message qui dit ce qui s'est réellement passé :

async function getJson(url) {
  const res = await fetch(url);
  const type = res.headers.get('content-type') || '';
  if (!res.ok || !type.includes('application/json')) {
    const body = await res.text();
    throw new Error(`Expected JSON from ${url}, got ${res.status} ${type}: ${body.slice(0, 100)}`);
  }
  return res.json();
}

Le même principe vaut côté serveur : faites renvoyer aux routes d'API des corps d'erreur en JSON plutôt que des pages d'erreur HTML, accompagnés de l'en-tête Content-Type: application/json. Pour le message voisin qui apparaît quand le corps est vide ou tronqué, consultez Unexpected end of JSON input.

Questions Fréquentes

Que signifie « Unexpected token < in JSON at position 0 » ?

La réponse commence par le caractère <, ce qui signifie qu'il s'agit de HTML et non de JSON : le plus souvent une page d'erreur, une page de connexion ou le fallback index.html. Vérifiez l'URL de la requête, le code de statut et l'en-tête Content-Type.

Pourquoi le message dit-il que « [object Object] » n'est pas un JSON valide ?

Vous avez passé un objet à JSON.parse. Il a d'abord été converti en texte [object Object]. La valeur est déjà analysée : utilisez-la directement.

Un validateur JSON peut-il trouver le problème ?

Oui, si le texte est censé être du JSON. Un validateur indique la position exacte de la première erreur. Si le texte est du HTML, la correction se fait côté serveur ou dans la requête, pas dans le JSON.