octobercms/october · error · Error
Broken JSON number body near ${body}
Error message
Broken JSON number body near ${body} What it means
The number branch of getBody() in the lenient JSON scanner: it collects characters from the set [0-9 + - .] and only returns when it reaches a character outside that set. If the input ends while the scan is still inside the number — no closing brace, quote, comma or whitespace terminates it — the loop falls off the end of the string and throws with the digits collected so far. Because the surrounding object parser also relies on a terminator, a shorthand attribute whose LAST value is a bare number and whose closing brace is missing will always hit this.
Source
Thrown at modules/system/assets/js/framework.js:2258
originLength: "null".length,
body: "null"
};
}
throw new Error("Broken JSON boolean body near " + str.substr(0, pos + 10));
}
if (str[pos] === "-" || str[pos] === "+" || str[pos] === "." || str[pos] >= "0" && str[pos] <= "9") {
var body = "";
for (var i = pos; i < str.length; i++) {
if (str[i] === "-" || str[i] === "+" || str[i] === "." || str[i] >= "0" && str[i] <= "9") {
body += str[i];
} else {
return {
originLength: body.length,
body
};
}
}
throw new Error("Broken JSON number body near " + body);
}
if (str[pos] === "{" || str[pos] === "[") {
var stack = [str[pos]];
var body = str[pos];
for (var i = pos + 1; i < str.length; i++) {
body += str[i];
if (str[i] === "\\") {
if (i + 1 < str.length) body += str[i + 1];
i++;
} else if (str[i] === '"') {
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();View on GitHub (pinned to b608633a7e)
Solutions
- Add the closing brace so the number is terminated: use the fully braced form data-request-data="{id: 5, page: 2}".
- Check the reported 'near <body>' digits against your attribute to confirm which value ran to the end.
- If the brace is present in source but missing at runtime, inspect the rendered HTML — a stray quote or templating bug is truncating the attribute.
Example fix
// before — last value runs to end of input
<a data-request="onPaginate" data-request-data="id: 5, page: 2">Next</a>
// after
<a data-request="onPaginate" data-request-data="{id: 5, page: 2}">Next</a> Defensive patterns
Strategy: validation
Validate before calling
// Shorthand values whose last value is numeric MUST carry their own closing brace
function needsClosingBrace(value) {
var v = value.trim();
return v.charAt(0) !== '{' && /[0-9.\-+]\s*$/.test(v);
} Prevention
- Always author data-request-data in the explicit braced form {k: v, k2: v2}.
- End attribute object values with the closing brace — the number scanner needs a terminator.
- In templates, assert generated attribute values start with '{' and end with '}'.
When it happens
Trigger: data-request-data="id: 5, page: 2" — paramToObj wraps it as {id: 5, page: 2}, the final '2' runs to end-of-input and throws; data-request-data="{id: 25" (explicit opening brace, missing close); oc.parseJSON('[1, 2').
Common situations: Using the convenient shorthand form (key: value without braces) where the last value is numeric — the wrapper only adds '{' and '}', but the trailing '}' is what the number scanner needs as terminator, so any omission truncates the number; partials rendered dynamically where the closing '}' gets dropped by templating or escaping.
Related errors
- Broken JSON string body near ${body}
- Broken JSON boolean body near ${str}
- Broken JSON ${str[pos] === "{" ? "object" : "array"} body ne
- 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/4fc05722b02b960f.
Report an issue: GitHub.