¿Rompe un BOM el análisis de JSON?
En resumen: Un BOM UTF-8 son tres bytes invisibles, así que JSON.parse falla en el primer carácter e informa de línea 1, columna 1, lo que hace que el archivo parezca vacío o truncado.

En resumen: comprueba los tres primeros bytes en busca de EF BB BF y vuelve a guardar como UTF-8 sin BOM; en el servidor, elimina un U+FEFF inicial antes de analizar cualquier archivo subido o de terceros, en lugar de depurar el fallo más tarde.
Sí, y produce el más confuso de todos los errores de análisis, porque el archivo parece perfectamente correcto.
Qué ves
SyntaxError: Unexpected token in JSON at position 0
Unexpected character '\uFEFF'
Ese carácter del mensaje es invisible. Position 0 significa el primer byte.
cat no muestra nada raro. hexdump -C file.json | head -1 sí:
00000000 ef bb bf 7b 0a 20 20 22 61 22 3a 20 31 0a 7d 0a |...{ "a": 1.}.|
7b es {. Los tres bytes anteriores son el BOM.
De dónde vienen los BOM
La marca de orden de bytes existía para UTF-16, donde el orden de bytes variaba de verdad. UTF-8 tiene un único orden de bytes, así que el BOM es pura sobrecarga; aun así, el Bloc de notas de Windows, algunas exportaciones de Excel y unos cuantos IDE antiguos siguen escribiéndolo de forma predeterminada.
RFC 8259 es inequívoco: el JSON intercambiado entre sistemas debe ser UTF-8, y las implementaciones no deben añadir un BOM. Los analizadores pueden ignorar un BOM inicial, pero no están obligados a ello. Los navegadores y Node eligen no hacerlo.
Tres formas de deshacerse de él
Guarda sin BOM. En VS Code, pulsa la codificación en la barra de estado y elige «Save with Encoding → UTF-8», no «UTF-8 with BOM».
Quítalo desde el shell.
sed -i '1s/^\xEF\xBB\xBF//' data.json
Quítalo al leer. Esta es la corrección duradera para todo lo que acepte archivos subidos o de terceros:
const text = require('node:fs').readFileSync('data.json', 'utf8').replace(/^\uFEFF/, '');
JSON.parse(text);
En Python, open(path, encoding='utf-8-sig') lo gestiona automáticamente.
Dos problemas similares
- Espacio de ancho cero (U+200B) — aparece al copiar JSON de una página web; síntoma idéntico, punto de código distinto.
- Comillas de ancho completo — un IME chino convierte
"key"en“key”, que parece casi idéntico pero falla comoUnexpected token “.
Los tres son fallos de caracteres invisibles. El diagnóstico es siempre el mismo: volcar los primeros bytes en hexadecimal en lugar de mirar fijamente el texto.
FAQ
¿Cómo puedo saber si un archivo empieza con un BOM?
cat no muestra nada, así que ejecuta hexdump -C file.json | head -1. Si la salida empieza por ef bb bf, el archivo tiene un BOM; 7b (el {) debería ir primero en un archivo UTF-8 limpio.
¿Por qué el error apunta siempre a la línea 1, columna 1?
El BOM está antes que todo lo demás, así que el primer carácter que lee el analizador es U+FEFF. Por eso el fallo cae al principio del archivo, lo que hace que el archivo parezca vacío.
¿Debería eliminar el BOM antes de analizar?
Sí. Cuando un servidor lee configuración o analiza archivos subidos, elimina primero un U+FEFF inicial —replace(/^\uFEFF/, '') en Node, encoding='utf-8-sig' en Python—, lo que es mucho más barato que diagnosticarlo después.