{"record":{"id":"5f0a05acd0400457","repo":"octobercms/october","slug":"broken-json-str-pos-object-array-5f0a05","errorCode":null,"errorMessage":"Broken JSON ${str[pos] === \"{\" ? \"object\" : \"array\"} body near ${body}","messagePattern":"Broken JSON (.+?) body near (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"modules/system/assets/js/framework.js","lineNumber":2287,"sourceCode":"            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();\n            } else if (stack[stack.length - 1] !== '\"') {\n              stack.push(str[i]);\n            }\n          } else if (stack[stack.length - 1] !== '\"' && stack[stack.length - 1] !== \"'\") {\n            if (str[i] === \"{\") {\n              stack.push(\"{\");\n            } else if (str[i] === \"}\") {\n              if (stack[stack.length - 1] === \"{\") {\n                stack.pop();\n              } else {\n                throw new Error(\"Broken JSON \" + (str[pos] === \"{\" ? \"object\" : \"array\") + \" body near \" + body);\n              }\n            } else if (str[i] === \"[\") {\n              stack.push(\"[\");\n            } else if (str[i] === \"]\") {\n              if (stack[stack.length - 1] === \"[\") {\n                stack.pop();\n              } else {\n                throw new Error(\"Broken JSON \" + (str[pos] === \"{\" ? \"object\" : \"array\") + \" body near \" + body);\n              }\n            }\n          }\n          if (!stack.length) {\n            return {\n              originLength: i - pos,\n              body\n            };\n          }\n        }","sourceCodeStart":2269,"sourceCodeEnd":2305,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/system/assets/js/framework.js#L2269-L2305","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n<div data-request-data=\"{ops: [1,2}}}\">...</div>\n\n// after\n<div data-request-data=\"{ops: [1,2]}\">...</div>","handlingStrategy":"validation","validationCode":"// Cheap bracket-order check on the raw value (ignores quoted content)\nfunction bracketsBalanceInOrder(value) {\n    var stack = [], pairs = {'}': '{', ']': '['};\n    for (var i = 0; i < value.length; i++) {\n        var ch = value[i];\n        if (ch === '{' || ch === '[') stack.push(ch);\n        else if (pairs[ch]) { if (stack.pop() !== pairs[ch]) return false; }\n    }\n    return stack.length === 0;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["json","parsing","frontend","data-attribute","bracket-mismatch"],"backgroundTag":"unbalanced-brackets","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}