Un error de token inesperado en JSON significa que tu analizador encontró un carácter que no esperaba al leer lo que se suponía era JSON válido. Casi nunca es un error misterioso. Se debe a una de seis causas concretas: una coma final, comillas simples, una respuesta HTML, una BOM invisible, claves sin comillas o comentarios. Esta guía explica cada una y, lo más importante, muestra cómo encontrar la línea y columna exactas en lugar de adivinar.
La parte frustrante es que el mensaje de error rara vez apunta al problema real. Token inesperado < en JSON en la posición 0 no significa que tu JSON esté roto. Significa que no estás viendo JSON en absoluto. Una vez que puedas leer lo que el analizador te dice, la mayoría de estas correcciones toman menos de un minuto.
Qué significa realmente "Token inesperado en JSON"#
JSON es un formato estricto. El analizador lee tu cadena carácter por carácter y construye un valor. En el momento en que ve algo que no puede aparecer legalmente en esa posición, se detiene y lanza un SyntaxError. El "token" es el carácter que lo desencadenó.
Los motores modernos expresan el mensaje de manera diferente, lo que añade confusión:
- V8 (Chrome, Node 20+):
Unexpected token 'x', "...contexto..." is not valid JSON - Node / Chrome antiguos:
Unexpected token x in JSON at position 42 - Firefox:
JSON.parse: unexpected character at line 2 column 5 of the JSON data - Safari:
JSON Parse error: Unexpected identifier
El campo más útil es la posición o el número de línea/columna. Firefox te da línea y columna directamente. V8 te da una posición en bytes y un fragmento del texto circundante. Lee eso primero, antes de leer cualquier otra cosa.
La forma más rápida de convertir una posición críptica en un problema visible es pegar la cadena sin procesar en un validador que resalte la línea problemática. Nuestro formateador y validador JSON gratuito marca el punto exacto y te dice qué esperaba allí, lo que reduce la mayor parte de la depuración a un vistazo.
Las 6 causas reales (y cómo solucionar cada una)#
Aquí está la distribución honesta. En la depuración real, la gran mayoría de estos errores son las causas 1 a 3. Las últimas tres son más raras, pero hacen perder horas porque son invisibles o contraintuitivas.
| Causa | Mensaje típico | Indicador |
|---|---|---|
| HTML en lugar de JSON | Unexpected token < en la posición 0 | El primer carácter es < (un <!DOCTYPE o <html>) |
| Coma final | Unexpected token } o ] | Una coma está antes de una llave o corchete de cierre |
| Comillas simples | Unexpected token ' | Las claves o cadenas usan ' en lugar de " |
| BOM / caracteres ocultos | Unexpected token en la posición 0 en JSON de aspecto válido | Se ve perfecto pero da error al inicio |
| Claves sin comillas | Unexpected token cerca de una clave | Una clave como name: no tiene comillas |
| Comentarios | Unexpected token / | Existe un comentario // o /* */ en el archivo |
Causa 1: Recibiste HTML, no JSON (el caso "token <")#
Esta es la que más confunde a la gente, y casi ninguna otra guía lo explica. Si ves Unexpected token < in JSON at position 0, el < es la apertura de una etiqueta HTML. Tu llamada fetch esperaba JSON pero el servidor devolvió una página HTML.
Generalmente significa una de estas:
- El endpoint devolvió una página de error 404 o 500 (HTML), no tu carga útil de API.
- Accediste a la URL incorrecta y recibiste el
index.htmlde la aplicación. - Un proxy, muro de inicio de sesión o limitador de velocidad interceptó la solicitud y sirvió una página HTML.
La solución no está en tu JSON. Registra el texto de respuesta sin procesar antes de analizarlo:
const res = await fetch(url);
const text = await res.text();
console.log(res.status, text.slice(0, 200)); // mira lo que realmente obtuviste
const data = JSON.parse(text);
Si text comienza con <!DOCTYPE html>, lo encontraste. Verifica el código de estado y la URL. También confirma que el Content-Type de la respuesta sea application/json, no text/html.
Causa 2: Coma final#
JSON no permite una coma después del último elemento en un objeto o arreglo. Los literales de objeto en JavaScript sí lo permiten, por eso esto se pasa por alto. Escribes JSON a mano como escribes JS, y el analizador lo rechaza.
{
"name": "Ada",
"role": "engineer", // esta coma final no es válida
}
Elimina la coma después de "engineer". Lo mismo aplica para arreglos: [1, 2, 3,] no es JSON válido. Un formateador detecta esto al instante porque la coma ofensiva está justo antes de } o ].
Causa 3: Comillas simples en lugar de comillas dobles#
JSON requiere comillas dobles tanto para las claves como para los valores de cadena. Las comillas simples son un hábito de JavaScript que JSON no comparte.
{ 'name': 'Ada' } // no válido: comillas simples por todas partes
{ "name": "Ada" } // válido
Si controlas la fuente, cambia cada ' a ". Si la cadena incorrecta proviene de algún lugar que no puedes editar, no hagas un reemplazo ciego con regex (los apóstrofes dentro de los valores se romperán). En su lugar, pásalo por una herramienta que entienda la estructura.
Causa 4: La BOM invisible (y CRLF de Windows)#
Esta desconcierta a la gente durante horas porque el JSON se ve perfecto. Ves JSON válido, lo pegas, y el analizador aún lanza un error en la posición 0. El culpable es una marca de orden de bytes, un carácter oculto U+FEFF que algunos editores (y la redirección > de PowerShell en Windows) anteponen a los archivos UTF-8.
El analizador lee la BOM como el primer token y la rechaza. Para confirmarlo, verifica los primeros bytes:
const text = fs.readFileSync("data.json", "utf8");
console.log(text.charCodeAt(0)); // 65279 significa que hay una BOM
const clean = text.replace(/^/, "");
JSON.parse(clean);
Guarda el archivo como UTF-8 sin BOM en tu editor (VS Code muestra la codificación en la barra de estado; haz clic y elige "Guardar con codificación"). En Windows, prefiere Out-File -Encoding utf8NoBOM o Set-Content en lugar de la redirección >, que puede inyectar la BOM. Los retornos de carro sobrantes de los saltos de línea CRLF pueden causar rarezas similares en la posición 0 cuando el JSON se concatena o transmite.
Causa 5: Claves sin comillas#
En JavaScript, { name: "Ada" } es válido. En JSON, la clave debe estar entre comillas: { "name": "Ada" }. Esto ocurre más a menudo cuando alguien copia un literal de objeto JS en un archivo .json o en el cuerpo de una API.
La solución es envolver cada clave entre comillas dobles. Si tienes un objeto grande, un formateador no pondrá comillas automáticamente en las claves (eso sería adivinar tu intención), pero señalará la clave exacta que falló para que puedas arreglarla rápido.
Causa 6: Comentarios#
JSON no tiene comentarios. Ni //, ni /* */. La gente los agrega a los archivos de configuración por costumbre y luego un analizador estricto se atraganta.
{
// configuración de la app <- no válido, JSON prohíbe comentarios
"port": 3000
}
Elimina los comentarios. Si realmente necesitas configuración comentada, usa un formato diseñado para ello (JSON5 o JSONC, que VS Code usa para su propia configuración) y analízalo con una biblioteca que soporte ese dialecto, no con JSON.parse simple.
Cómo encontrar la línea y columna exactas del error#
Esta habilidad convierte una búsqueda de 30 minutos en una solución de 30 segundos, y es la parte que la mayoría de los resultados de búsqueda omiten por completo. El error te da una posición; aquí te mostramos cómo convertirla en una ubicación real.
Paso 1: Lee la posición o línea/columna del error#
Captura el error completo, no solo la primera palabra. En Node o el navegador, envuelve el parse:
try {
JSON.parse(raw);
} catch (e) {
console.error(e.message); // incluye posición o línea:columna
}
Firefox ya te da línea X columna Y. V8 te da una posición en bytes. Anota ese número, lo usarás a continuación.
Paso 2: Salta a esa posición en la cadena original#
Si tienes una posición en bytes (por ejemplo, 142), corta alrededor para ver el contexto que el analizador vio:
console.log(raw.slice(130, 160));
El carácter en el límite es tu culpable. Ver 15 caracteres a cada lado casi siempre hace obvia la causa: una coma extra, una comilla simple, una etiqueta HTML.
Paso 3: Pégalo en un validador que resalte el punto#
Examinar posiciones en una cadena larga es lento y propenso a errores. Pega el JSON sin procesar en el formateador y validador JSON, que embellece la estructura y marca la línea fallida con un mensaje claro sobre lo que esperaba. El propio reformateo a menudo revela el problema, porque una coma mal colocada o un corchete sin cerrar se vuelve visualmente obvio una vez que el anidamiento está indentado correctamente.
Paso 4: Corrige, revalida y luego vuelve a probar en código#
Aplica la corrección, valida de nuevo para confirmar que la cadena ahora está limpia, luego ejecuta tu ruta de código real. Si el JSON provino de una API, corrígelo en la fuente si puedes, en lugar de parchear la cadena del lado del cliente. Una respuesta limpia supera a una cadena de .replace() defensiva cada vez.
Cómo evitar el error antes de que ocurra#
La mayoría de estos errores se pueden evitar con algunos hábitos. El objetivo es nunca escribir JSON a mano cuando tus herramientas pueden generarlo correctamente.
- Nunca construyas JSON mediante concatenación de cadenas. Usa
JSON.stringify()para que las comillas y las comas siempre sean correctas. Si no estás seguro de cómo debería verse el resultado, nuestra guía sobre cómo formatear JSON en JavaScript cubreJSON.stringifyy sus detalles. - Siempre registra la respuesta sin procesar antes de analizarla en un resultado de API, para que un
<(HTML) aparezca de inmediato en lugar de como un error de token misterioso. - Verifica primero el estado HTTP. Si
res.okes falso, léelo como texto y muestra la página de error en lugar de analizarla a ciegas. - Guarda los archivos de configuración como UTF-8 sin BOM y mantén un formateador en tu flujo de trabajo diario. Si trabajas con JSON, descubre por qué el formateador de JSON es una herramienta diaria para desarrolladores para detectar estos problemas antes de que lleguen a producción.
- Revisa tu JSON en CI. Un esquema o un paso simple de análisis en tu pipeline detecta una coma final antes de que llegue a producción.
Conclusión: Lee la posición, luego identifica la causa#
Un error de token inesperado en JSON parece aleatorio hasta que te das cuenta de que es uno de seis problemas predecibles, y el analizador ya te dijo dónde buscar. Empieza por la posición o la línea y columna, luego asocia el carácter que falla con la causa: < significa HTML, una coma antes de } indica una coma final, una ' significa comillas simples, y un error en la posición 0 en un JSON que parece perfecto casi siempre indica una BOM oculta.
Cuando quieras dejar de entrecerrar los ojos ante los desplazamientos de bytes, pega la cadena en un validador que resalte la línea exacta y muestre lo que esperaba. Ese solo paso reemplaza la mayor parte de la búsqueda manual y te permite volver a construir.
Preguntas Frecuentes#
¿Qué significa "Unexpected token < in JSON at position 0"?
Significa que la respuesta que intentaste analizar comienza con un <, que es la apertura de una etiqueta HTML, no JSON. Tu código esperaba JSON pero el servidor devolvió una página HTML, generalmente una página de error 404 o 500, una redirección de inicio de sesión o la URL incorrecta. Registra el texto de respuesta sin procesar y verifica el código de estado para confirmarlo.
¿Por qué mi JSON de aspecto válido arroja un error en la posición 0?
La causa más común es una marca de orden de bytes (BOM) invisible, un carácter oculto U+FEFF que algunos editores y shells de Windows añaden a los archivos UTF-8. El JSON se ve perfecto pero el analizador lee primero el BOM y lo rechaza. Elimínalo con text.replace(/^/, "") o guarda el archivo como UTF-8 sin BOM.
¿Se permiten comas finales en JSON?
No. Una coma después del último elemento en un objeto o arreglo es JSON inválido, aunque los literales de objeto en JavaScript lo permitan. Esta es una de las causas más frecuentes de errores de token inesperado. Elimina la coma que está justo antes de cualquier } o ].
¿Puedo usar comillas simples en JSON?
No. JSON requiere comillas dobles para cada clave y cada valor de cadena. Las comillas simples son válidas en JavaScript pero no en JSON, por lo que { 'nombre': 'Ada' } arrojará un error, mientras que { "nombre": "Ada" } se analiza correctamente.
¿Cómo encuentro la línea exacta que causa el error JSON? Primero lee la posición o línea y columna del mensaje de error, ya que el analizador indica dónde falló. Corta la cadena sin procesar alrededor de esa posición para ver el contexto, o pega toda la cadena en el validador y formateador de JSON para resaltar la línea fallida y mostrar qué carácter esperaba allí.
¿JSON admite comentarios?
JSON plano no admite comentarios de ningún tipo, por lo que // y /* */ causarán un error de token inesperado. Si necesitas configuración comentada, usa JSON5 o JSONC (el dialecto que VS Code usa para su configuración) y analízalo con una biblioteca que entienda esos formatos en lugar de JSON.parse.



