zloirock/core-js · error · SyntaxError
Unterminated object at: ${i}
Error message
Unterminated object at: ${i} What it means
Thrown by the object() parser of the core-js JSON.parse polyfill when it reaches the end of the input while scanning an object without finding the closing '}'. The object was opened but never terminated, so the JSON is incomplete.
Source
Thrown at packages/core-js/modules/es.json.parse.js:162
i = result.end;
i = this.until([':'], i) + 1;
// Parsing value
i = this.skip(IS_WHITESPACE, i);
result = this.fork(i).parse();
createProperty(nodes, key, result);
createProperty(object, key, result.value);
i = this.until([',', '}'], result.end);
var chr = at(source, i);
if (chr === ',') {
expectKeypair = true;
i++;
} else if (chr === '}') {
i++;
closed = true;
break;
}
}
if (!closed) throw new SyntaxError('Unterminated object at: ' + i);
return this.node(OBJECT, object, this.index, i, nodes);
},
array: function () {
var source = this.source;
var i = this.index + 1;
var expectElement = false;
var array = [];
var nodes = [];
var closed = false;
while (i < source.length) {
i = this.skip(IS_WHITESPACE, i);
if (at(source, i) === ']' && !expectElement) {
i++;
closed = true;
break;
}
var result = this.fork(i).parse();
push(nodes, result);View on GitHub (pinned to 84e45fba09)
Solutions
- Check the source string: ensure it is complete and ends with the matching '}' — log its length and tail before parsing
- Verify the transport: check Content-Length vs actual body size, and retry the request if the response was truncated
- Fix the code that builds the JSON so every '{' has a matching '}' (build objects and use JSON.stringify instead of string concatenation)
- Read files fully (no premature size cap) and confirm EOF before parsing
Example fix
// before
let json = '{"a":1';
const data = JSON.parse(json);
// after
const obj = { a: 1 };
const data = JSON.parse(JSON.stringify(obj)); // always well-formed Defensive patterns
Strategy: validation
Validate before calling
function isCompleteJsonObject(s) {
if (typeof s !== 'string') return false;
const t = s.trim();
if (!t.startsWith('{')) return false;
try { JSON.parse(t); return true; } catch { return false; }
}
if (!isCompleteJsonObject(body)) throw new Error('incomplete JSON body'); Type guard
function isBalancedBraces(s) {
if (typeof s !== 'string') return false;
let depth = 0, inStr = false, esc = false;
for (const c of s) {
if (esc) { esc = false; continue; }
if (c === '\\' && inStr) { esc = true; continue; }
if (c === '"') inStr = !inStr;
else if (!inStr) {
if (c === '{') depth++;
if (c === '}') depth--;
if (depth < 0) return false;
}
}
return depth === 0 && !inStr;
} Try / catch
let data;
try {
data = JSON.parse(body);
} catch (e) {
if (e instanceof SyntaxError && /Unterminated object/.test(e.message)) {
throw new Error('Response truncated; retry the request');
}
throw e;
} Prevention
- Compare received body length against Content-Length and retry on mismatch
- Buffer streamed/chunked responses until fully received before parsing
- Build JSON via JSON.stringify of real objects instead of manual string assembly
- For files, read to EOF and check the write process completed before parsing
When it happens
Trigger: JSON.parse() with input like '{"a":1' or '{' — the string ends (or a nested construct consumed to the end) before a matching '}' appears.
Common situations: Truncated network responses (connection dropped, response cut by proxy/timeout); files read with a byte limit or partially written; string built by concatenation where the closing brace was omitted; copying JSON and missing the final characters.
Related errors
- Unterminated array at: ${i}
- Unexpected extra character: "${chr}" after the parsed data a
- Unexpected character: "${chr}" 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/fca723ffa51ed432.
Report an issue: GitHub.