Unexpected end of JSON input: что значит и как исправить

JSON пустой или обрывается раньше, чем закончился документ

Unexpected end of JSON input значит, что текст закончился раньше, чем JSON: парсер ждал значение, закрывающую кавычку или скобку, а символов больше нет. Чаще всего разбирают пустую строку — ответ без тела, — реже обрезанный файл или ответ. Сначала проверьте, пришло ли что-нибудь вообще, затем — не оборван ли конец.

Как выглядит ошибка в разных программах

Для пустой строки сообщения такие:

  • Chrome, Edge и Node.js: SyntaxError: Unexpected end of JSON input;
  • Firefox: SyntaxError: JSON.parse: unexpected end of data at line 1 column 1 of the JSON data;
  • Safari: SyntaxError: JSON Parse error: Unexpected EOF;
  • Python: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0).

У Python это сообщение не только про пустую строку: «Expecting value» в строке 1, колонке 1 значит, что в самом начале нет значения JSON. Так же Python отвечает, если вместо JSON пришла HTML-страница, — тогда смотрите статью про Unexpected token. Если строка пустая, но в ней есть пробелы или перенос, номер колонки или строки будет больше единицы.

Пустой ответ сервера

Самая частая причина в браузере: код вызывает response.json(), а у ответа нет тела. response.json() на пустом теле падает так же, как JSON.parse(''). Когда так бывает:

  • статус 204 No Content — сервер успешно выполнил запрос, например удаление, и по стандарту ничего не вернул;
  • запрос HEAD или ответ 304 Not Modified — тела нет по определению;
  • бэкенд упал или вернул пустую строку с кодом 200 или 500 — тогда виноват сервер;
  • запрос с mode: 'no-cors' — браузер отдаёт коду непрозрачный ответ с пустым телом, даже если сервер что-то прислал;
  • в JSON.parse передают пустую переменную: JSON.parse(''), JSON.parse(localStorage.getItem(key) ?? '').

Перед разбором проверьте статус и наличие текста:

Разбирать только непустой ответ
const response = await fetch('/api/orders/1057', { method: 'DELETE' });
if (!response.ok) throw new Error(`HTTP ${response.status}`);

const text = await response.text();
const data = text ? JSON.parse(text) : null;

Во вкладке «Сеть» инструментов разработчика (F12) видно, пришло ли что-нибудь: статус, размер ответа и пустая вкладка тела сразу подтвердят причину.

Обрезанный ответ или файл

Если JSON не пустой, а оборванный, сообщение Chrome может быть тем же, а Firefox и Python укажут место — самый конец текста. Причины:

  • соединение оборвалось на середине ответа, или файл недокачался;
  • лимит размера: прокси, шлюз или библиотека обрезали длинный ответ;
  • строка лога упёрлась в лимит длины — многие системы логирования отрезают длинные строки без предупреждения;
  • ответ нейросети упёрся в лимит токенов и закончился на середине JSON;
  • при копировании из консоли браузера длинное значение было сокращено.

Учтите: новые Chrome и Node.js пишут «Unexpected end of JSON input» не для любого обрыва. Если текст кончился после значения внутри объекта, сообщение будет Expected ',' or '}' after property value in JSON at position …, а если внутри строки — Unterminated string in JSON at position …. Признак обрыва тот же: позиция равна длине текста. Python в таких случаях пишет «Expecting ',' delimiter» или «Unterminated string starting at», а jq — «Unfinished JSON term at EOF» (внутри строки — «Unfinished string at EOF»).

Уведомление ЮKassa, обрезанное в логе
{"type":"notification","event":"payment.succeeded","object":{"id":"2d5e3a7f-000f-5000-9000-1a2b3c4d5e6f","status":"succeeded","amount":{"value":"1990.00","currency":"RUB"},"metadata":{"order_id":"1057"

Незакрытая скобка или кавычка

Документ может быть целым, но с ошибкой: при ручной правке удалили } или ], не закрыли кавычку строки. Тогда парсер дочитывает текст до конца в поисках закрывающего символа и сообщает о неожиданном конце, хотя ошибка где-то в середине. В большом файле это самый неприятный случай: сообщение указывает на последний символ, а потерянная скобка может быть в сотне строк выше.

Как найти, где обрывается JSON

Вставьте текст в проверку JSON на parsetools. Для обрыва она пишет, чего именно не хватает и где это началось: «JSON обрывается: не хватает ] — массив открыт в строке 3». Если скобок не хватает несколько, будет ошибка на каждую, с номером строки, где открыт соответствующий объект или массив. Для незакрытой строки — «Строка не закрыта: нет " до конца строки» с указанием места, где она началась.

Если скобку потеряли в середине, а документ продолжается, проверка ловит это там, где встретилась чужая скобка: ] закрывает массив, а объект внутри так и не закрыт — «Не хватает } — объект открыт в строке 12». Если же потерянной скобке нечем выдать себя до конца текста, ошибка встанет на последний символ — но номер строки, где открыт незакрытый объект или массив, всё равно сузит поиск. Текст не уходит на сервер: проверка работает в браузере, поэтому в неё можно вставлять и логи с платёжными данными.

Как дописать недостающий конец

Починка JSON закрывает недописанный конец: незакрытую строку, затем массивы и объекты в правильном порядке. Ключ, у которого не успело появиться значение, получает null. В списке исправлений над результатом будет видно, что именно закрыто, и отдельная пометка, что JSON был обрезан.

Обрезанный ответ API
{"items":[{"id":1,"name":"Чай"},{"id":2,"name":"Кофе"
После починки
{
  "items": [
    { "id": 1, "name": "Чай" },
    { "id": 2, "name": "Кофе" }
  ]
}

Починка делает документ разбираемым, но не восстанавливает потерянное: если оборвался список товаров, последних позиций в нём не будет. Для отладки и просмотра этого хватает. Если важны все данные — итоговая сумма, последние записи, — получите JSON заново: повторите запрос, скачайте файл ещё раз, увеличьте лимит длины строки в логах или лимит токенов модели.

Частые вопросы

Unexpected end of JSON input что значит

Текст закончился раньше, чем JSON: парсер ждал значение или закрывающую скобку. Чаще всего разбирают пустую строку, реже — обрезанный документ или документ с потерянной скобкой.

Почему response.json() выдаёт Unexpected end of JSON input

У ответа нет тела: статус 204, ответ на HEAD, пустой ответ упавшего сервера или запрос в режиме no-cors. Прочитайте ответ через response.text() и разбирайте, только если текст не пустой.

Что значит unexpected end of data at line 1 column 1 в Firefox

Это то же самое в формулировке Firefox: строка 1, колонка 1 значат, что текст пустой. Проверьте статус и тело ответа во вкладке «Сеть».

Expecting value: line 1 column 1 (char 0) в Python

В начале текста нет значения JSON. Обычно строка пустая или вместо JSON пришла HTML-страница. Выведите response.status_code и response.text[:200], чтобы увидеть, что пришло.

Как восстановить обрезанный JSON

Вставьте его в починку: она закроет незакрытые строки, массивы и объекты и покажет, что добавила. Потерянные в конце данные она не восстановит — для этого JSON нужно получить заново.

Инструменты по теме

Ещё в справке