Búsqueda de mensajes de error de JSON: del texto del error a la solución
En resumen: Busca la causa por el mensaje exacto de JSON.parse: 12 errores frecuentes en Chrome, Firefox y Safari, incluidos páginas de error HTML, truncamiento y doble análisis.

En resumen: cuando aparezca un error de JSON.parse, quédate primero con la posición y el token; una posición 0 significa que hay que revisar si la respuesta es HTML, un BOM o un tipo equivocado, y un mensaje "Expected" significa que hay que mirar el carácter anterior: no vuelvas a leer línea por línea desde la posición indicada.
El texto del error no es ruido: es la respuesta. El analizador te dice qué carácter encontró, qué esperaba y qué recibió realmente. Buscar por el mensaje de error es mejor que reescribir todo el documento a mano.
Todo error de JSON.parse() tiene tres partes: la posición (un desplazamiento de caracteres, o línea/columna), la expectativa (Expected...) y la realidad (Unexpected token X, o xxx is not valid JSON). Los motores las formulan de forma distinta —Chrome y Node (V8) dicen Expected ',' or '}' after property value in JSON at position 25, Firefox dice JSON.parse: expected ',' or '}' after property value in object at line 3 column 1, Safari dice JSON Parse error: Expected ',' or '}'— pero los tres apuntan a la misma ruptura de sintaxis. Cuando busques un error, ignora la redacción y quédate con los tres hechos: qué carácter, qué se esperaba y qué llegó.
1. La tabla de búsqueda de los 12 errores
La columna izquierda es el fragmento más identificable de tu consola (redacción de V8). Las variantes de Firefox/Safari van entre paréntesis.
| Texto del error (V8) | Causa real | Solución |
|---|---|---|
Unexpected token < in JSON at position 0 |
La API devolvió HTML (página 404, plantilla 500, redirección al login, fallback del proxy), no JSON | Comprueba primero response.status y Content-Type; no arregles el JSON |
Unexpected end of JSON input |
La entrada está vacía o truncada: cuerpo vacío, 204, descarga interrumpida, copia a la que le falta la última línea | Controla el caso vacío, compara Content-Length para encontrar el corte |
Unexpected token o / "[object Object]" is not valid JSON |
Se pasó otra vez a JSON.parse() un objeto ya analizado y se coercionó a cadena |
Comprueba typeof; si es un objeto, úsalo directamente |
"undefined" is not valid JSON |
La variable nunca se asignó (JSON.parse(undefined)) |
Inicializa valores de reserva; comprueba antes de analizar |
Expected double-quoted property name in JSON |
Una coma final ({"a": 1,}); el analizador espera otra clave y encuentra } |
Elimina la coma después del último elemento |
Expected property name or '}' in JSON |
Una clave sin comillas o entre comillas simples ({name: "Ada"}, {'name': 'Ada'}) |
Pon comillas dobles en todas las claves |
Expected ',' or '}' after property value in JSON |
Falta una coma ({"a": 1 "b": 2}) o hay un comentario después de un valor |
Añade la coma; elimina el comentario |
Unexpected token '/' |
Un comentario // o /* */ dentro de JSON |
Elimínalo, o analiza la configuración como JSONC |
Bad control character in string literal |
Un salto de línea, tabulador u otro carácter de control U+0000–U+001F en bruto dentro de una cadena | Escribe \n; genera con JSON.stringify |
Unterminated string in JSON |
Una cadena abierta con " y nunca cerrada, o una comilla interna sin escapar |
Escapa las comillas internas como \" |
Unexpected non-whitespace character after JSON |
Dos documentos en un mismo texto: {}{}, NDJSON, un envoltorio JSONP |
Divide por líneas y analiza cada una, o usa un analizador NDJSON |
JSON.parse is not a function |
Una variable tuya está ocultando el JSON global |
Renombra la variable; nunca la llames JSON |
Los dos primeros merecen una mirada más atenta, porque ninguno significa "tu JSON está mal", sino "lo que recibiste no es lo que crees".
2. Tres fuentes habituales de un error en la posición 0
Una posición 0 significa que el primer carácter es ilegal. Si nada parece sospechoso, probablemente el carácter sea invisible. Tres sospechosos habituales:
Primero: <, es decir, HTML. Es el error de análisis más común en producción. Una URL equivocada, una sesión caducada redirigida por el gateway o una plantilla de error del servidor: el cuerpo empieza por <!DOCTYPE html> y el analizador se detiene en el primer carácter. Lo correcto es abrir el panel de red y leer la respuesta en bruto, y después arreglar la llamada a la API, no el JSON.
Segundo: un BOM o caracteres de ancho cero. Los archivos guardados con el Bloc de notas de Windows suelen empezar con un BOM UTF-8 (\uFEFF), y el texto copiado de páginas web o de aplicaciones de chat puede traer espacios de ancho cero (\u200B–\u200D). Para ti son invisibles, para el analizador son evidentes:
// Quita el BOM y los caracteres de ancho cero antes de analizar
const cleaned = raw.replace(/^\uFEFF/, '').replace(/[\u200B-\u200D]/g, '');
const data = JSON.parse(cleaned);
Tercero: el tipo equivocado. JSON.parse(undefined) informa de "undefined" is not valid JSON; JSON.parse(someObject) informa de Unexpected token o (el objeto se coerciona a "[object Object]", y o es ilegal en la posición 1). Ambos significan "los datos ya están analizados" o "nunca hubo datos". Revisa el tipo, no la sintaxis:
let data = text;
if (typeof data === 'string') {
data = JSON.parse(data); // Analiza solo cuando realmente es una cadena
}
3. La posición apunta aguas abajo; la causa está aguas arriba
Hay dos errores que engañan sobre la ubicación, y son las dos entradas que más se malinterpretan de la tabla:
- Una coma ausente:
{"a": 1 "b": 2}informa deExpected ',' or '}' after property valueen la línea de"b". El informe es correcto, pero la corrección pertenece al final de la línea anterior. - Un corchete de cierre ausente: un anidamiento profundo al que le falta un
}o un]hace que el analizador se trague todo hasta el final de la entrada e informe deUnexpected end of JSON input. La posición es el final del archivo; el hueco real puede estar mucho antes. Busca hacia atrás el{o[sin cerrar más reciente: contar pares es mejor que mirar a ojo.
La técnica general es la bisección: corta el texto antes de la posición indicada y analízalo por separado. Si se analiza, el problema está cerca de la posición indicada; si no, bisecciona más atrás. El límite del primer fragmento que falla es el lugar real del error. Para archivos grandes, formatea primero el documento: con la indentación alineada, el nivel que falta se ve de un vistazo (el formateador JSON en línea sirve perfectamente para esto).
4. Cuatro estados "falsamente sanos" que se analizan bien pero se comportan mal
Peor que un error es no tener error y tener datos equivocados. En los cuatro casos el JSON es válido y el analizador está contento; el problema es la forma de los datos:
- Doble codificación: todo el documento se pasó dos veces por
JSON.stringify, así que el análisis devuelve una cadena, no un objeto. Sitypeof result === 'string', analiza otra vez, pero busca y corrige la doble serialización en el origen. - Las claves duplicadas se sobrescriben en silencio:
{"name": "Tom", "name": "Jerry"}es JSON válido, la mayoría de los analizadores no se queja y gana el segundo valor. Esto muerde al fusionar datos de varias fuentes; sácalo a la superficie con un validador JSON estricto antes de que te muerda. - NDJSON tratado como un solo documento: las API de streaming emiten un objeto por línea; analizar todo el texto falla con
Unexpected non-whitespace character after JSON. Divide por\ny analiza línea a línea. - Pérdida silenciosa de precisión numérica: los enteros por encima de
2^53 - 1(ID de tipo snowflake) vuelven con los últimos dígitos puestos a cero, sin ningún error. Transmite los ID como cadenas.
El hilo común: el analizador cree que todo está bien. Así que cuando los datos de la API parezcan erróneos, imprime primero los 80 primeros caracteres del texto en bruto y su typeof: confirma la forma antes de discutir el contenido.
5. Haz que los errores sean imposibles en el momento de escribir
La tabla de búsqueda es la herramienta a posteriori; la prevención es la herramienta a priori. Cuatro hábitos interceptan la mayoría de los errores antes de que ocurran:
// 1. Dos comprobaciones antes de analizar cualquier respuesta
const response = await fetch('/api/users');
if (!response.ok) {
throw new Error(`HTTP ${response.status}: la API no devolvió datos`);
}
const contentType = response.headers.get('content-type') ?? '';
if (!contentType.includes('application/json')) {
throw new Error(`Se esperaba JSON, se recibió ${contentType}`);
}
const data = await response.json(); // 2. json() ya analiza: no analices de nuevo
- Serializa para generar, nunca concatenes:
JSON.stringify()trata correctamente las comillas, los saltos de línea y los caracteres de control; las cadenas construidas a mano son la principal fuente deBad control characteryUnterminated string. - Captura siempre: un error lanzado por
JSON.parsees un fallo síncrono a menos que algo lo capture. Para entradas no confiables (localStorage, archivos externos), el bloque catch necesita un valor por defecto o un reporte de error explícito. - Delega la estructura al Schema: sintaxis válida no significa estructura válida. Los campos ausentes y los tipos equivocados corresponden a la validación con JSON Schema en el límite; consulta qué resuelve JSON Schema.
6. La ruta rápida de decisión
Resume todo el artículo en un único orden de decisión. Cuando veas un error, quédate primero con la posición y el token:
- Posición 0 → revisa las tres fuentes:
<(HTML), BOM, tipo equivocado; end of input→ revisa si el cuerpo está vacío o truncado, y después busca hacia atrás corchetes sin cerrar;Expected ...→ mira el carácter anterior; normalmente es una coma o una comilla que falta;after JSON data→ se concatenaron varios documentos; divide por línea;- Se analiza bien pero los datos parecen erróneos → ejecuta las cuatro comprobaciones de "falso sano".
Combinado con el triaje paso a paso de cómo corregir errores de análisis JSON, el 90% de los problemas de análisis se resuelven en cinco minutos. Mantén el propio texto del error entre tus marcadores: es el registro de depuración que el analizador escribió para ti, su redacción cambia una vez cada tres años y una sola búsqueda rinde todo un año.
¿Qué significa "Unexpected token in JSON"?
El analizador encontró un carácter ilegal en ese punto según la gramática JSON. El token es el carácter rechazado: < suele significar que la API devolvió HTML, ' significa comillas simples, / significa un comentario, y una letra normal suele significar una clave sin comillas o un literal exclusivo de JavaScript como undefined o NaN. Lee primero el token, después la posición, y la causa queda reducida a una.
¿Cómo corrijo "Unexpected end of JSON input"?
Dos orígenes: entrada vacía (un cuerpo de respuesta vacío, o una cadena vacía en localStorage) o entrada truncada (una descarga interrumpida, una copia a la que le falta la última línea, un límite de tamaño). Controla el caso vacío con if (!text) return; después verifica la completitud y cierra el {, [ o " sin cerrar más reciente. Ten en cuenta que el error también puede venir de un corchete profundamente ausente: la posición coincide por casualidad con el final del archivo.
¿Por qué Chrome, Firefox y Safari informan de los errores de forma distinta?
Los tres navegadores incluyen motores JS distintos (V8, SpiderMonkey, JavaScriptCore), y cada uno formula sus errores a su manera; MDN documenta todas las variantes oficiales. Pero los tres errores llevan los mismos tres elementos —posición, expectativa, realidad— con semántica uno a uno. Traduce a la redacción de V8 y usa esta tabla tal cual.
La posición del error apunta a un lugar que parece correcto: ¿y ahora qué?
El error real está antes. Casos típicos: una coma ausente (se indica en la línea siguiente) y un corchete de cierre ausente (se indica al final del archivo). Recorre hacia atrás desde la posición indicada token a token, o bisecciona: analiza la primera mitad por separado y el límite del primer fragmento que falla es el lugar real del error.