Tu fixes une stack trace rouge : SyntaxError: Unexpected token '<', "..." is not valid JSON. Ou peut-être Unexpected token u in JSON at position 0. Quoi qu'il en soit, JSON.parse() a refusé de tourner et ton code s'est arrêté. Ce guide explique précisément ce que signifie chaque variante de cette erreur, pourquoi elle arrive et comment la corriger —— vite.
À quoi ressemble vraiment l'erreur
La formulation varie selon le moteur JavaScript, mais ça veut dire la même chose : le parser a rencontré un caractère qu'il n'attendait pas à une position précise dans ta chaîne.
// V8 (Chrome, Node.js, Edge)
SyntaxError: Unexpected token '<', "<html>..." is not valid JSON
SyntaxError: Unexpected token 'u', "undefined" is not valid JSON
SyntaxError: Unexpected token u in JSON at position 0 // V8 plus ancien
SyntaxError: Expected ',' or '}' after property value in JSON at position 42
// Firefox (SpiderMonkey)
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
SyntaxError: JSON.parse: unexpected non-whitespace character after JSON data
// Safari (JavaScriptCore)
SyntaxError: JSON Parse error: Unexpected identifier "undefined"
SyntaxError: JSON Parse error: Single quotes (') are not allowed in JSONL'info clé est toujours en deux parties : quel caractère était inattendu et où. Le caractère te dit ce que le parser a reçu ; la position te dit où regarder dans la chaîne.
Cause 1 : le serveur a renvoyé du HTML au lieu de JSON
C'est la cause la plus fréquente de Unexpected token '<'. Ton fetch ou appel AJAX a récupéré une page HTML —— en général une page 404, un redirect de login, ou une erreur serveur —— au lieu du JSON attendu. Le < est l'ouverture de <!DOCTYPE html> ou <html>.
// ❌ Ça plante avec "Unexpected token '<'"
const res = await fetch('/api/user');
const data = await res.json(); // le serveur a renvoyé une HTML 404
// ✅ Vérifie d'abord le status de la réponse
const res = await fetch('/api/user');
if (!res.ok) {
throw new Error(`HTTP ${res.status}: ${res.statusText}`);
}
const data = await res.json(); Toujours vérifier res.ok (ou res.status) avant d'appeler res.json(). Tu peux aussi inspecter le texte brut de la réponse d'abord :
const text = await res.text();
console.log(text.slice(0, 200)); // regarde ce que tu as vraiment reçu
const data = JSON.parse(text);Cause 2 : la valeur est undefined
Unexpected token 'u' en position 0 signifie presque toujours que tu as appelé JSON.parse(undefined). La chaîne "undefined" commence par la lettre u, qui n'est pas un caractère de début JSON valide.
// ❌ la variable n'a jamais été assignée
const raw = localStorage.getItem('settings'); // renvoie null si absent
JSON.parse(raw); // null est OK, mais si raw est undefined d'une manière...
// ❌ données async pas encore chargées
JSON.parse(this.state.data); // data est undefined au premier render
// ✅ Guard avant de parser
if (raw) {
const data = JSON.parse(raw);
} Note que localStorage.getItem() renvoie null (pas undefined) pour des clés manquantes, et JSON.parse(null) renvoie null sans erreur. Les coupables habituels sont des variables d'état non initialisées ou un argument de fonction manquant.
Cause 3 : guillemets simples au lieu de doubles
// ❌ SyntaxError: Unexpected token '''
JSON.parse("{'name': 'Ada'}");
// ✅ JSON exige des guillemets doubles
JSON.parse('{"name": "Ada"}')Les littéraux d'objet JavaScript acceptent les guillemets simples. JSON non —— toutes les chaînes, clés incluses, doivent utiliser des guillemets doubles. Ça arrive souvent quand quelqu'un sérialise des données avec la fonction str() de Python au lieu de json.dumps(), ou copie un littéral d'objet directement.
Cause 4 : virgule finale
// ❌ SyntaxError: Unexpected token '}'
JSON.parse('{"name": "Ada", "score": 98,}');
// ^ virgule finale
// ✅
JSON.parse('{"name": "Ada", "score": 98}')JavaScript moderne autorise les virgules finales dans les arrays et objets. JSON non. Les fichiers de config JSON édités à la main sont la source la plus courante de cette erreur.
Cause 5 : clés sans guillemets
// ❌ SyntaxError: Unexpected token 'n'
JSON.parse("{name: 'Ada'}");
// ✅
JSON.parse('{"name": "Ada"}') Les clés d'objet en JSON doivent toujours être des chaînes entre guillemets doubles. Des identifiants nus comme name sont valides dans les littéraux d'objet JavaScript mais pas en JSON.
Cause 6 : commentaires dans le JSON
// ❌ SyntaxError: Unexpected token '/'
JSON.parse(`{
// enregistrement utilisateur
"name": "Ada"
}`);
// ✅ Vire les commentaires avant de parser (ou utilise un parser JSONC)
const stripped = raw.replace(///.*$/gm, '').replace(//*[sS]*?*//g, '');
JSON.parse(stripped);JSON n'a pas de syntaxe de commentaires. Les commentaires sont souvent ajoutés aux fichiers de config (le format JSONC), mais le JSON.parse() standard les rejettera immédiatement.
Cause 7 : un BOM ou caractère invisible en position 0
Si l'erreur dit position 0 mais que le premier caractère visible a l'air bien, il peut y avoir un byte-order mark invisible (BOM, U+FEFF) ou un autre caractère de contrôle ajouté en tête de la chaîne —— typique quand on lit un fichier sauvegardé en encodage UTF-8-BOM sur Windows.
// ✅ Retire le BOM avant de parser
const clean = raw.replace(/^/, '');
JSON.parse(clean);Cause 8 : tokens I ou N —— Infinity et NaN
Si l'erreur dit Unexpected token I ou Unexpected token N, la source a produit Infinity, -Infinity, ou NaN —— tous valides en JavaScript mais pas en JSON.
// ❌ Erreur côté producteur
const json = '{"ratio": NaN, "limit": Infinity}';
JSON.parse(json); // Unexpected token N (or I) ...
// ✅ Encode-les délibérément
const safe = JSON.stringify({ ratio: NaN, limit: Infinity });
// → '{"ratio":null,"limit":null}' (note : avec perte —— les deux deviennent null)
// ✅ Sans perte : encode comme une chaîne sentinelle que tu re-parses toi-même
JSON.stringify({ ratio: 'NaN', limit: 'Infinity' });JSON.stringify convertit silencieusement NaN / Infinity en null. Si tu en as besoin pour un round-trip, remplace-les par une chaîne sentinelle en sortie et reparse-la en entrée.
Comment trouver la position exacte de l'erreur
Le message d'erreur inclut un numéro de position. Utilise-le pour slicer la chaîne et voir exactement ce qu'il y a là :
function parseWithContext(text) {
try {
return JSON.parse(text);
} catch (err) {
// Extrait la position du message d'erreur V8
const match = err.message.match(/position (\d+)/);
if (match) {
const pos = Number(match[1]);
const snippet = text.slice(Math.max(0, pos - 20), pos + 20);
console.error(`Error near: ..."${snippet}"...`);
console.error(` ${''.padStart(Math.min(pos, 20), ' ')}^`);
}
throw err;
}
}Foire aux questions
Que signifie « Unexpected token in JSON » ?
Ça veut dire que JSON.parse() a rencontré un caractère qui n'est pas valide à ce point de la grammaire. Le token nommé te dit ce qui a été reçu (< = HTML, u = undefined, ' = guillemet simple) et la position te dit où chercher.
Pourquoi « Unexpected token '<' » arrive-t-il avec fetch ?
Ta requête a renvoyé une page HTML —— un 404, un redirect de login, ou une erreur serveur —— au lieu de JSON, et le < est la balise HTML ouvrante. Vérifie response.ok avant d'appeler response.json() et logge await response.text() pour voir ce qui est vraiment revenu.
Comment corriger « Unexpected token u in JSON at position 0 » ?
Tu as passé undefined à JSON.parse(). Guard la valeur d'abord (if (raw) JSON.parse(raw)) et vérifie un état non initialisé ou un argument de fonction manquant. La variante étroitement liée token o est traitée dans Unexpected token o in JSON.
Comment trouver la position exacte de l'erreur ?
Lis le numéro de position dans le message d'erreur et slice la chaîne autour (voir snippet ci-dessus), ou colle le JSON dans JSON Fix, qui met en évidence la ligne fautive exacte.
Le correctif le plus rapide : coller et réparer en ligne
Si tu as une chaîne JSON cassée et juste besoin qu'elle soit corrigée maintenant, JSON Fix gère toutes les causes ci-dessus automatiquement —— guillemets simples, virgules finales, clés sans guillemets, commentaires, littéraux Python, et plus. Colle ton JSON, clique sur Repair & Format, et récupère du JSON valide et propre en une étape. Tout tourne dans ton navigateur ; rien n'est envoyé vers un serveur.
- JSON Fix —— auto-répare du JSON cassé et affiche la ligne d'erreur exacte
- Corriger les erreurs JSON Unexpected Token —— référence rapide pour chaque variante d'unexpected token
- Corriger « [object Object] is Not Valid JSON » —— l'erreur liée quand un objet est coercié en chaîne avant le parsing
- JSON Diff —— compare un JSON avant/après pour vérifier que ton correctif n'a pas changé quelque chose d'inattendu