{"record":{"id":"ce0543a890ecc26b","repo":"zloirock/core-js","slug":"unexpected-character-chr-at-i","errorCode":null,"errorMessage":"Unexpected character: \"${chr}\" at: ${i}","messagePattern":"Unexpected character: \"(.+?)\" at: (.+?)","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"packages/core-js/modules/es.json.parse.js","lineNumber":122,"sourceCode":"    var source = this.source;\n    var i = this.skip(IS_WHITESPACE, this.index);\n    var fork = this.fork(i);\n    var chr = at(source, i);\n    if (exec(IS_NUMBER_START, chr)) return fork.number();\n    switch (chr) {\n      case '{':\n        return fork.object();\n      case '[':\n        return fork.array();\n      case '\"':\n        return fork.string();\n      case 't':\n        return fork.keyword(true);\n      case 'f':\n        return fork.keyword(false);\n      case 'n':\n        return fork.keyword(null);\n    } throw new SyntaxError('Unexpected character: \"' + chr + '\" at: ' + i);\n  },\n  node: function (type, value, start, end, nodes) {\n    return new Node(value, end, type ? null : slice(this.source, start, end), nodes);\n  },\n  object: function () {\n    var source = this.source;\n    var i = this.index + 1;\n    var expectKeypair = false;\n    var object = {};\n    var nodes = {};\n    var closed = false;\n    while (i < source.length) {\n      i = this.until(['\"', '}'], i);\n      if (at(source, i) === '}' && !expectKeypair) {\n        i++;\n        closed = true;\n        break;\n      }","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/zloirock/core-js/blob/84e45fba098dd3a177d5cf2247d06ab8e98d3790/packages/core-js/modules/es.json.parse.js#L104-L140","documentation":"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.","triggerScenarios":"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'\").","commonSituations":"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.","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)"],"exampleFix":"// before\nconst json = \"{ name: 'bob', age: \" + age + \" }\"; // age === undefined\nJSON.parse(json);\n// after\nconst json = JSON.stringify({ name: 'bob', age: age ?? null });\nconst parsed = JSON.parse(json);","handlingStrategy":"validation","validationCode":"function isParseableJson(s) {\n  if (typeof s !== 'string' || s.trim() === '') return false;\n  try { JSON.parse(s); return true; } catch { return false; }\n}\nif (!isParseableJson(payload)) {\n  payload = JSON.stringify(payload ?? null); // re-serialize from a real JS value\n}","typeGuard":"function isJsonPrimitiveToken(c) {\n  return c === '{' || c === '[' || c === '\"' || c === '-' || (c >= '0' && c <= '9') || c === 't' || c === 'f' || c === 'n';\n}","tryCatchPattern":"let value;\ntry {\n  value = JSON.parse(raw);\n} catch (e) {\n  if (e instanceof SyntaxError && /Unexpected character/.test(e.message)) {\n    const i = Number(e.message.match(/at: (\\d+)$/)?.[1] ?? NaN);\n    console.error('Invalid JSON token at index', i, 'context:', raw.slice(Math.max(0, i - 20), i + 20));\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["json","syntax-error","parsing","unexpected-token"],"backgroundTag":"unexpected-token-in-json","analyzedSha":"84e45fba098dd3a177d5cf2247d06ab8e98d3790","analyzedAt":"2026-08-30T20:36:10.323Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}