octobercms/october · error · Error

Broken JSON object near ${result}

Error message

Broken JSON object near ${result}

What it means

Thrown at the end of the object branch of JsonParser.parseString (October CMS AJAX framework). The state machine walks the {..} literal key-by-key (needKey/needBody states, lenient commas, relaxed quotes) and returns only when it places the closing '}'. If the input ends before that brace is produced, the partial result accumulated so far is reported and the parse aborts.

Source

Thrown at modules/system/assets/js/framework.js:2146

          } else if (type === "afterBody" || type === "needKey") {
            var last = i;
            while (str[last] === "," || this.isBlankChar(str[last])) {
              last++;
            }
            if (str[last] === "}" && last === str.length - 1) {
              while (result[result.length - 1] === ",") {
                result = result.substr(0, result.length - 1);
              }
              result += "}";
              return result;
            } else if (last !== i && result !== "{") {
              result += ",";
              type = "needKey";
              i = last - 1;
            }
          }
        }
        throw new Error("Broken JSON object near " + result);
      }
      if (str[0] === "[") {
        var result = "[";
        var type = "needBody";
        for (var i = 1; i < str.length; i++) {
          if (" " === str[i] || "\n" === str[i] || "	" === str[i]) {
            continue;
          } else if (type === "needBody") {
            if (str[i] === ",") {
              result += "null,";
              continue;
            }
            if (str[i] === "]" && i === str.length - 1) {
              if (result[result.length - 1] === ",") result = result.substr(0, result.length - 1);
              result += "]";
              return result;
            }
            var body = this.getBody(str, i);

View on GitHub (pinned to b608633a7e)

Solutions

  1. Append the missing closing '}' to the object literal
  2. Fix any inner incomplete value first - a broken value can consume the real closer
  3. Round-trip the value through oc.parseJSON (or strict JSON.parse) in the console/CI to catch unclosed objects before shipping markup

Example fix

<!-- before -->
<div data-request-data="{page: 2, sort: 'name'">...</div>

<!-- after -->
<div data-request-data="{page: 2, sort: 'name'}">...</div>
Defensive patterns

Strategy: try-catch

Validate before calling

function objectLiteralCloses(s) {
  const t = s.trim();
  if (t[0] !== '{') return true;
  const closes = (t.match(/}/g) || []).length;
  const opens = (t.match(/{/g) || []).length;
  return closes === opens;
}

Try / catch

try { const d = oc.parseJSON(raw); } catch (e) { if (/Broken JSON object near/.test(e.message)) console.error('Unterminated { - missing closing brace:', e.message); }

Prevention

When it happens

Trigger: oc.parseJSON("{a: 1") or data-request-data="{page: 2, sort: 'name'" - object literal missing its final }; also inner values left mid-way ({a: ) that consume input without completing the state machine.

Common situations: Hand-edited attribute values missing the closing brace; template concatenation dropping the last character; partial JSON pasted into markup; refactors that delete the trailing } while editing the last pair.

Related errors


AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21). Data as JSON: /api/errors/3d38a4224992bde6. Report an issue: GitHub.