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

  1. Check the source string: ensure it is complete and ends with the matching '}' — log its length and tail before parsing
  2. Verify the transport: check Content-Length vs actual body size, and retry the request if the response was truncated
  3. Fix the code that builds the JSON so every '{' has a matching '}' (build objects and use JSON.stringify instead of string concatenation)
  4. 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

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


AI-assisted analysis of zloirock/core-js@84e45fba09 (2026-08-30). Data as JSON: /api/errors/fca723ffa51ed432. Report an issue: GitHub.