{"record":{"id":"306dda3dbd7a61b7","repo":"octobercms/october","slug":"broken-json-str-pos-object-array","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-bundle.js","lineNumber":2306,"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":2288,"sourceCodeEnd":2324,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/system/assets/js/framework-bundle.js#L2288-L2324","documentation":"Thrown while JsonParser.getBody bracket-matches an object or array body in October CMS's relaxed JSON. The parser keeps a stack of open brackets and quotes; when it encounters '}' and the innermost open bracket is not '{' (for example a '{' appearing while only '[' is open), the structure cannot be balanced and it throws, echoing the body scanned so far.","triggerScenarios":"oc.parseJSON(\"{items: [1,2}}\") - the first '}' closes nothing because the top of the stack is '['; likewise data-request-update=\"{'partial': '#id'}}\" with an extra closing brace inside a nested array context.","commonSituations":"Extra '}' typed at the end of hand-written attribute values; nesting edits (adding an array literal) without updating brackets; regex/string processing of attributes that appends stray braces; minified or hand-compressed markup losing a ']' before a '}'.","solutions":["Balance the brackets in the attribute value: add the missing ']' (e.g. {items: [1,2]}) and remove the extra '}'","Run the value through a bracket-balance check or oc.parseJSON before wiring it to a request","Author the attribute as strict JSON generated by JSON.stringify/json_encode so tooling can validate it"],"exampleFix":"<!-- before -->\n<div data-request-data=\"{items: [1,2}}\">...</div>\n\n<!-- after -->\n<div data-request-data=\"{items: [1,2]}\">...</div>","handlingStrategy":"validation","validationCode":"function bracketsBalanced(s) {\n  let depth = 0;\n  for (const ch of s) {\n    if (ch === '{' || ch === '[') depth++;\n    else if (ch === '}' || ch === ']') depth--;\n    if (depth < 0) return false; // closer with nothing open\n  }\n  return depth === 0;\n}\nconst ok = bracketsBalanced(el.getAttribute('data-request-data') || '');","typeGuard":null,"tryCatchPattern":"try { oc.request(el, 'onGo'); } catch (e) { if (/Broken JSON (object|array) body/.test(e.message)) { console.error('Unbalanced brackets in data attributes:', e.message); } }","preventionTips":["Auto-close/format JSON in the editor rather than editing brackets by hand","After editing nested values, re-run oc.parseJSON in the console","Prefer strict JSON in attributes so standard linters can validate them"],"tags":["json","ajax","html-attribute","parser","brackets"],"backgroundTag":"json-bracket-mismatch","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}