octobercms/october · error · Error
Broken JSON ${str[pos] === "{" ? "object" : "array"} body ne
Error message
Broken JSON ${str[pos] === "{" ? "object" : "array"} body near ${body} What it means
When getBody() reaches an object or array value, it runs a bracket-matching scan using a stack that also tracks embedded quotes. This specific throw fires when a closing '}' arrives while the innermost open bracket on the stack is not '{' — a mismatched close. The message names 'object' or 'array' according to the composite being scanned and echoes everything consumed so far.
Source
Thrown at modules/system/assets/js/framework.js:2287
if (stack[stack.length - 1] === '"') {
stack.pop();
} else if (stack[stack.length - 1] !== "'") {
stack.push(str[i]);
}
} else if (str[i] === "'") {
if (stack[stack.length - 1] === "'") {
stack.pop();
} else if (stack[stack.length - 1] !== '"') {
stack.push(str[i]);
}
} else if (stack[stack.length - 1] !== '"' && stack[stack.length - 1] !== "'") {
if (str[i] === "{") {
stack.push("{");
} else if (str[i] === "}") {
if (stack[stack.length - 1] === "{") {
stack.pop();
} else {
throw new Error("Broken JSON " + (str[pos] === "{" ? "object" : "array") + " body near " + body);
}
} else if (str[i] === "[") {
stack.push("[");
} else if (str[i] === "]") {
if (stack[stack.length - 1] === "[") {
stack.pop();
} else {
throw new Error("Broken JSON " + (str[pos] === "{" ? "object" : "array") + " body near " + body);
}
}
}
if (!stack.length) {
return {
originLength: i - pos,
body
};
}
}View on GitHub (pinned to b608633a7e)
Solutions
- Fix the bracket order at the reported position — the 'near ...' body shows the scan up to the mismatched '}'.
- Validate complex nested values with JSON.parse in the console first (adding quotes to keys/strings) before pasting into the attribute.
- For deeply nested data prefer moving it out of the attribute (e.g. a hidden input or AJAX fetch) instead of inline JSON.
Example fix
// before
<div data-request-data="{ops: [1,2}}}">...</div>
// after
<div data-request-data="{ops: [1,2]}">...</div> Defensive patterns
Strategy: validation
Validate before calling
// Cheap bracket-order check on the raw value (ignores quoted content)
function bracketsBalanceInOrder(value) {
var stack = [], pairs = {'}': '{', ']': '['};
for (var i = 0; i < value.length; i++) {
var ch = value[i];
if (ch === '{' || ch === '[') stack.push(ch);
else if (pairs[ch]) { if (stack.pop() !== pairs[ch]) return false; }
}
return stack.length === 0;
} Prevention
- Lint inline JSON in markup with a bracket-balance check in CI.
- Keep inline composite values shallow; move deep structures to data islands or AJAX.
- Use JSON.parse on a quoted version of the value in the console before pasting into markup.
When it happens
Trigger: oc.parseJSON("{'a': [1, 2}}") — the '}' closes while '[' is innermost; an attribute like data-request-data="{ops: [1,2}}}"; any swapped/redundant closing brace inside an inline object/array value.
Common situations: Hand-written nested inline JSON in data attributes where brackets are closed in the wrong order; template concatenation that appends a stray '}' when conditionally building attribute values.
Related errors
- Broken JSON string body near ${body}
- Broken JSON boolean body near ${str}
- Broken JSON number body near ${body}
- Broken JSON body near ${str}
- Broken JSON boolean body near ${str}
AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21).
Data as JSON: /api/errors/5f0a05acd0400457.
Report an issue: GitHub.