← Tous les articles

Unexpected End of JSON Input : pourquoi ça arrive et comment corriger

Le parseur a atteint la fin de la chaîne avant que la structure ne soit complète. Les causes vont des réponses d'API tronquées aux crochets non fermés et aux chaînes vides. Cinq patterns, cinq correctifs.

SyntaxError: Unexpected end of JSON input signifie que le parser a atteint la fin de la chaîne avant que la structure JSON soit complète. Les données ont été coupées. Cet article montre tous les cas courants où ça arrive et comment corriger chacun.

Ce que signifie l’erreur

JSON.parse() est une machine à états. Il lit les caractères un par un en suivant les crochets, accolades et délimiteurs de chaîne ouverts. Quand il atteint la fin de l’entrée alors qu’il est encore « à l’intérieur de quelque chose » —— un objet, un tableau, une chaîne —— il jette :

SyntaxError: Unexpected end of JSON input

L’erreur ne donne ni numéro de ligne ni position parce que le problème est l’absence de contenu —— il n’y a rien à pointer.

Cause 1 —— Réponse d’API tronquée

La cause la plus courante en pratique. Le serveur a envoyé un gros corps JSON et soit le réseau a coupé tôt, soit la réponse a été lue avant la fin, soit une limite de buffering d’un proxy ou d’un CDN a été atteinte.

// Ce qui est arrivé (connexion coupée en plein milieu) :
'{"users":[{"id":1,"name":"Ada"},{"id":2,"na'

JSON.parse('{"users":[{"id":1,...') // SyntaxError: Unexpected end of JSON input

Correction : Vérifiez le code HTTP et l’en-tête Content-Length. Loguez la longueur du corps brut avant le parsing. Si vous utilisez fetch, faites toujours await sur response.json() plutôt que lire response.text() et parser à la main —— le parser JSON intégré du navigateur donne une erreur plus claire en cas de troncature.

// Correct
const data = await response.json();

// Fragile —— masque les erreurs de troncature
const text = await response.text();
const data = JSON.parse(text);

Cause 2 —— Objet ou tableau non refermé

Le JSON a été écrit à la main ou généré par du code qui a oublié un crochet ou une accolade fermante.

JSON.parse('{"name":"Ada","plan":"pro"')
// } de fermeture manquante
// SyntaxError: Unexpected end of JSON input

JSON.parse('[1, 2, 3')
// ] de fermeture manquante
// SyntaxError: Unexpected end of JSON input

Correction : Utilisez un linter JSON ou collez la chaîne dans JSON Fix —— il identifie le délimiteur non fermé et, en mode permissif, peut ajouter automatiquement le crochet manquant.

Cause 3 —— Chaîne non refermée

Une valeur de type chaîne qui n’a jamais été terminée par un guillemet double fermant, souvent parce que la valeur contenait un guillemet double non échappé :

JSON.parse('{"title":"He said "hello" to her"}')
//                              ^ le guillemet non échappé referme la chaîne trop tôt
// SyntaxError: Unexpected end of JSON input

// Correct —— échappez les guillemets internes avec antislash :
JSON.parse('{"title":"He said \"hello\" to her"}')

Correction : Échappez les guillemets doubles internes en \", ou utilisez JSON.stringify() pour construire le JSON dès le départ plutôt que d’assembler des chaînes à la main.

Cause 4 —— Chaîne vide

Passer une chaîne vide ou ne contenant que des espaces à JSON.parse() jette la même erreur —— il n’y a tout simplement rien à parser.

JSON.parse('')   // SyntaxError: Unexpected end of JSON input
JSON.parse('  ') // SyntaxError: Unexpected end of JSON input
JSON.parse()     // SyntaxError: Unexpected token u… (undefined casté en chaîne)

Ça arrive souvent quand un champ de formulaire, une clé localStorage ou une variable d’environnement est vide.

// Garde avant parsing
const raw = localStorage.getItem('session');
if (!raw) return null;
return JSON.parse(raw);

Cause 5 —— Réponse en streaming lue trop tôt

En consommant une API en streaming ou un WebSocket, il est facile de tenter de parser un chunk avant que le message complet soit arrivé.

// ❌ Tente de parser un chunk incomplet
ws.onmessage = (event) => {
  const data = JSON.parse(event.data); // peut être partiel
};

// ✓ Bufferisez jusqu’à la frontière de message (framing applicatif)
let buffer = '';
ws.onmessage = (event) => {
  buffer += event.data;
  if (buffer.endsWith('\n')) {        // ou vérifier un délimiteur connu
    const data = JSON.parse(buffer.trim());
    buffer = '';
  }
};

Diagnostiquer la troncature : Content-Length et le streaming reader

Deux techniques concrètes pour confirmer si la réponse a été coupée :

  • Comparez à Content-Length. Si le serveur l’a renseigné, vous pouvez détecter une lecture trop courte directement :
    const res = await fetch(url);
    const expected = Number(res.headers.get('Content-Length') ?? NaN);
    const text = await res.text();
    if (Number.isFinite(expected) && text.length !== expected) {
      throw new Error(`truncated: got ${text.length} of ${expected} bytes`);
    }

    Note : Content-Length peut être absent pour les réponses chunked/compressées.

  • Lisez avec le streaming body reader. Utiliser res.body.getReader() vous laisse observer l’arrivée chunk par chunk et remarquer si le stream se ferme en plein payload —— c’est le symptôme d’une connexion coupée ou d’un timeout de proxy. Le navigateur remonte la panne réseau sous-jacente sous forme de rejet de fetch si le stream avorte ; combinez avec l’erreur du parser pour être sûr.

Checklist rapide de diagnostic

  • Loguez typeof input et input.length juste avant l’appel à parse.
  • Si la longueur paraît trop courte, la réponse a été tronquée —— vérifiez les logs réseau.
  • Si la longueur est 0, la source (API, stockage, variable d’env) n’a rien renvoyé —— ajoutez une garde.
  • Si la longueur paraît correcte, collez la chaîne dans JSON Fix pour trouver le problème structurel.

Récupérer avec grâce en production

function safeParse(text, fallback = null) {
  if (!text || !text.trim()) return fallback;
  try {
    return JSON.parse(text);
  } catch {
    console.error('JSON parse failed, input length:', text.length);
    return fallback;
  }
}

Questions fréquentes

Qu’est-ce qui cause « Unexpected end of JSON input » ?

Le parser a atteint la fin de la chaîne alors qu’il était encore dans un objet, un tableau ou une chaîne —— les données étaient incomplètes. La cause la plus fréquente en pratique est une réponse d’API tronquée ; d’autres incluent un crochet non fermé, une chaîne non terminée ou une chaîne vide.

Pourquoi pas de numéro de ligne ni de position ?

Parce que le problème est du contenu manquant, pas un caractère faux. Il n’y a rien à pointer pour le parser —— il a simplement épuisé l’entrée avant la fermeture de la structure.

Comment corriger pour une chaîne vide ?

Mettez une garde avant le parsing : if (!raw || !raw.trim()) return fallback;. Champs de formulaire vides, clés localStorage manquantes et variables d’environnement non définies sont les sources habituelles.

Comment le gérer avec grâce en production ?

Enveloppez JSON.parse() dans un helper safeParse qui renvoie un fallback en cas d’échec (voir le snippet ci-dessus), et loguez la longueur de l’entrée pour distinguer la troncature d’une structure malformée. Pour l’ensemble des patterns, voir gérer du JSON cassé en JavaScript.

Corriger du JSON tronqué dans votre navigateur

Une chaîne JSON cassée à inspecter ou réparer ? JSON Fix sur fixjson.org parse, valide et auto-répare les erreurs structurelles courantes —— y compris les crochets manquants —— directement dans le navigateur, sans envoyer de données à un serveur.