Чи ламає BOM розбір JSON
Головне: UTF-8 BOM — це три невидимі байти, тож JSON.parse зазнає збою на першому символі й повідомляє рядок 1, стовпець 1, через що файл виглядає порожнім або обрізаним.

Коротко: перевірте перші три байти на EF BB BF і збережіть знову як UTF-8 без BOM; на сервері видаляйте провідний U+FEFF перед розбором будь-якого завантаженого чи стороннього файлу, замість налагоджувати збій потім.
Так — і це дає найзаплутанішу з усіх помилок розбору, бо файл виглядає цілком нормально.
Що ви бачите
SyntaxError: Unexpected token in JSON at position 0
Unexpected character '\uFEFF'
Той символ у повідомленні невидимий. Позиція 0 означає найперший байт.
cat не показує нічого незвичайного. hexdump -C file.json | head -1 показує:
00000000 ef bb bf 7b 0a 20 20 22 61 22 3a 20 31 0a 7d 0a |...{ "a": 1.}.|
7b — це {. Три байти перед ним — це BOM.
Звідки беруться BOM
Маркер порядку байтів існував для UTF-16, де порядок байтів справді різнився. UTF-8 має єдиний порядок байтів, тож BOM — чиста надлишковість — але Notepad у Windows, деякі експорти Excel і кілька старіших IDE усе ще пишуть його за замовчуванням.
RFC 8259 однозначний: JSON, що обмінюється між системами, мусить бути UTF-8, а реалізації не повинні додавати BOM. Парсери можуть ігнорувати провідний BOM, але не зобовʼязані. Браузери й Node обирають не ігнорувати.
Три способи його позбутися
Збережіть без BOM. У VS Code натисніть кодування в рядку стану й оберіть «Save with Encoding → UTF-8», а не «UTF-8 with BOM».
Видаліть його з оболонки.
sed -i '1s/^\xEF\xBB\xBF//' data.json
Видаляйте під час читання. Це довговічне виправлення для всього, що приймає завантажені чи сторонні файли:
const text = require('node:fs').readFileSync('data.json', 'utf8').replace(/^\uFEFF/, '');
JSON.parse(text);
У Python open(path, encoding='utf-8-sig') обробляє це автоматично.
Дві схожі проблеми
- Пробіл нульової ширини (U+200B) — потрапляє під час копіювання JSON зі сторінки; ідентичний симптом, інша кодова точка.
- Повноширинні лапки — китайська IME перетворює
"key"на“key”, що виглядає майже ідентично, але зазнає збою якUnexpected token “.
Усі три — баги невидимих символів. Діагностика завжди та сама: виведіть перші байти в шістнадцятковому вигляді, а не вдивляйтеся в текст.
Часті питання
Як визначити, чи файл починається з BOM?
cat нічого не показує, тож запустіть hexdump -C file.json | head -1. Якщо вивід починається з ef bb bf, файл має BOM; 7b (це {) має йти першим у чистому файлі UTF-8.
Чому помилка завжди вказує на рядок 1, стовпець 1?
BOM сидить перед усім іншим, тож перший символ, який читає парсер, — U+FEFF. Збій тому припадає на початок файлу, через що файл виглядає порожнім.
Чи видаляти BOM перед розбором?
Так. Коли сервер читає конфігурацію або розбирає завантажені файли, спершу видаліть провідний U+FEFF — replace(/^\uFEFF/, '') у Node, encoding='utf-8-sig' у Python — що набагато дешевше, ніж діагностувати це потім.