{"record":{"id":"a9c02759ce96a4af","repo":"octobercms/october","slug":"broken-json-number-body-near-body","errorCode":null,"errorMessage":"Broken JSON number body near ${body}","messagePattern":"Broken JSON number body near (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"modules/system/assets/js/framework-bundle.js","lineNumber":2277,"sourceCode":"            originLength: \"null\".length,\n            body: \"null\"\n          };\n        }\n        throw new Error(\"Broken JSON boolean body near \" + str.substr(0, pos + 10));\n      }\n      if (str[pos] === \"-\" || str[pos] === \"+\" || str[pos] === \".\" || str[pos] >= \"0\" && str[pos] <= \"9\") {\n        var body = \"\";\n        for (var i = pos; i < str.length; i++) {\n          if (str[i] === \"-\" || str[i] === \"+\" || str[i] === \".\" || str[i] >= \"0\" && str[i] <= \"9\") {\n            body += str[i];\n          } else {\n            return {\n              originLength: body.length,\n              body\n            };\n          }\n        }\n        throw new Error(\"Broken JSON number body near \" + body);\n      }\n      if (str[pos] === \"{\" || str[pos] === \"[\") {\n        var stack = [str[pos]];\n        var body = str[pos];\n        for (var i = pos + 1; i < str.length; i++) {\n          body += str[i];\n          if (str[i] === \"\\\\\") {\n            if (i + 1 < str.length) body += str[i + 1];\n            i++;\n          } else if (str[i] === '\"') {\n            if (stack[stack.length - 1] === '\"') {\n              stack.pop();\n            } else if (stack[stack.length - 1] !== \"'\") {\n              stack.push(str[i]);\n            }\n          } else if (str[i] === \"'\") {\n            if (stack[stack.length - 1] === \"'\") {\n              stack.pop();","sourceCodeStart":2259,"sourceCodeEnd":2295,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/system/assets/js/framework-bundle.js#L2259-L2295","documentation":"Thrown by JsonParser.getBody in October CMS's AJAX framework while scanning a numeric token. The scanner accepts digits, '-', '+' and '.' and only terminates a number when it hits a non-numeric character; if the digits run all the way to the end of the input, there is no closing delimiter, which means the surrounding JSON structure was truncated, so it throws with the number scanned so far.","triggerScenarios":"oc.parseJSON(\"{page: 3\") or data-request-data=\"{count: 5\" - any attribute value ending in a bare number with the closing brace/bracket or quote missing. The parser reaches end-of-string while still inside the number token and throws.","commonSituations":"Truncated attribute values from string concatenation in templates; manually edited data-request-data where the closing } was deleted; AJAX-injected HTML where the attribute got cut off; copy-pasting JSON fragments that lost their tail.","solutions":["Close the unterminated container: append the missing } or ] (or closing quote) to the attribute value","If building the value dynamically, use JSON.stringify/oc.values to serialize instead of string concatenation","Lint the attribute with oc.parseJSON (or strict JSON.parse) before triggering the request to catch truncation early"],"exampleFix":"// before\nel.setAttribute('data-request-data', '{page: ' + page);\n\n// after\nel.setAttribute('data-request-data', JSON.stringify({ page: page }));","handlingStrategy":"try-catch","validationCode":"// Numbers in the attribute must be followed by a delimiter before end of input\nfunction endsWithClosedContainer(v) {\n  return /[\\}\"'\\]]\\s*$/.test(v.trim());\n}","typeGuard":null,"tryCatchPattern":"try {\n  const data = oc.parseJSON(raw);\n} catch (e) {\n  if (/Broken JSON number body/.test(e.message)) {\n    console.error('Truncated numeric value - missing closing } or ]:', e.message);\n  }\n}","preventionTips":["Never build attribute JSON by string concatenation; use JSON.stringify","Treat 'value ends in digits' as a truncation smell when reviewing markup","Round-trip generated markup through a JSON validator in CI"],"tags":["json","ajax","html-attribute","parser","truncation"],"backgroundTag":"malformed-json","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}