zloirock/core-js · error · SyntaxError
Unexpected character: "${chr}" at: ${i}
Error message
Unexpected character: "${chr}" at: ${i} What it means
Thrown by the value-parsing branch of the core-js JSON.parse polyfill when the character at the current position cannot start any JSON value (true, false, null, number, string, object, or array). Native JSON.parse calls this 'Unexpected token'; the polyfill reports the character and its index.
Source
Thrown at packages/core-js/modules/es.json.parse.js:122
var source = this.source;
var i = this.skip(IS_WHITESPACE, this.index);
var fork = this.fork(i);
var chr = at(source, i);
if (exec(IS_NUMBER_START, chr)) return fork.number();
switch (chr) {
case '{':
return fork.object();
case '[':
return fork.array();
case '"':
return fork.string();
case 't':
return fork.keyword(true);
case 'f':
return fork.keyword(false);
case 'n':
return fork.keyword(null);
} throw new SyntaxError('Unexpected character: "' + chr + '" at: ' + i);
},
node: function (type, value, start, end, nodes) {
return new Node(value, end, type ? null : slice(this.source, start, end), nodes);
},
object: function () {
var source = this.source;
var i = this.index + 1;
var expectKeypair = false;
var object = {};
var nodes = {};
var closed = false;
while (i < source.length) {
i = this.until(['"', '}'], i);
if (at(source, i) === '}' && !expectKeypair) {
i++;
closed = true;
break;
}View on GitHub (pinned to 84e45fba09)
Solutions
- Look at the character and index in the message to locate the invalid token and fix the JSON source
- Quote all keys with double quotes and use only double-quoted strings inside JSON
- Replace undefined/NaN/Infinity with null (or valid values) before serializing; use JSON.stringify which converts them to null
- Validate the payload with JSON.parse inside try/catch or a schema validator before relying on it; if the producer is JS, log JSON.stringify(value) instead of String(value)
Example fix
// before
const json = "{ name: 'bob', age: " + age + " }"; // age === undefined
JSON.parse(json);
// after
const json = JSON.stringify({ name: 'bob', age: age ?? null });
const parsed = JSON.parse(json); Defensive patterns
Strategy: validation
Validate before calling
function isParseableJson(s) {
if (typeof s !== 'string' || s.trim() === '') return false;
try { JSON.parse(s); return true; } catch { return false; }
}
if (!isParseableJson(payload)) {
payload = JSON.stringify(payload ?? null); // re-serialize from a real JS value
} Type guard
function isJsonPrimitiveToken(c) {
return c === '{' || c === '[' || c === '"' || c === '-' || (c >= '0' && c <= '9') || c === 't' || c === 'f' || c === 'n';
} Try / catch
let value;
try {
value = JSON.parse(raw);
} catch (e) {
if (e instanceof SyntaxError && /Unexpected character/.test(e.message)) {
const i = Number(e.message.match(/at: (\d+)$/)?.[1] ?? NaN);
console.error('Invalid JSON token at index', i, 'context:', raw.slice(Math.max(0, i - 20), i + 20));
}
throw e;
} Prevention
- Always produce JSON with JSON.stringify, never by string concatenation or template literals
- Sanitize undefined/NaN/Infinity/functions before serializing (JSON.stringify maps them to null)
- Reject or sanitize single quotes and unquoted keys in hand-edited JSON (lint JSON config files)
- Validate external payloads with a JSON Schema validator before use
When it happens
Trigger: JSON.parse() input where a value position holds something like undefined, a bare word (NaN, Infinity, a JS identifier), single-quoted text, or a stray character, e.g. JSON.parse("{a:1}") (key not quoted), JSON.parse("undefined"), or JSON.parse("'hello'").
Common situations: Stringifying JavaScript objects with undefined/NaN/Infinity or functions and feeding the result back as JSON; hand-written JSON with unquoted keys or single quotes; templates that interpolate undefined into the JSON string; server returning a JS-object literal instead of JSON.
Related errors
- Unexpected extra character: "${chr}" after the parsed data a
- Unterminated object at: ${i}
- Unterminated array at: ${i}
- Failed to parse number at: ${i}
- Failed to parse number's fraction at: ${i}
AI-assisted analysis of zloirock/core-js@84e45fba09 (2026-08-30).
Data as JSON: /api/errors/ce0543a890ecc26b.
Report an issue: GitHub.