{"record":{"id":"3d38a4224992bde6","repo":"octobercms/october","slug":"broken-json-object-near-result","errorCode":null,"errorMessage":"Broken JSON object near ${result}","messagePattern":"Broken JSON object near (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"modules/system/assets/js/framework.js","lineNumber":2146,"sourceCode":"          } else if (type === \"afterBody\" || type === \"needKey\") {\n            var last = i;\n            while (str[last] === \",\" || this.isBlankChar(str[last])) {\n              last++;\n            }\n            if (str[last] === \"}\" && last === str.length - 1) {\n              while (result[result.length - 1] === \",\") {\n                result = result.substr(0, result.length - 1);\n              }\n              result += \"}\";\n              return result;\n            } else if (last !== i && result !== \"{\") {\n              result += \",\";\n              type = \"needKey\";\n              i = last - 1;\n            }\n          }\n        }\n        throw new Error(\"Broken JSON object near \" + result);\n      }\n      if (str[0] === \"[\") {\n        var result = \"[\";\n        var type = \"needBody\";\n        for (var i = 1; i < str.length; i++) {\n          if (\" \" === str[i] || \"\\n\" === str[i] || \"\t\" === str[i]) {\n            continue;\n          } else if (type === \"needBody\") {\n            if (str[i] === \",\") {\n              result += \"null,\";\n              continue;\n            }\n            if (str[i] === \"]\" && i === str.length - 1) {\n              if (result[result.length - 1] === \",\") result = result.substr(0, result.length - 1);\n              result += \"]\";\n              return result;\n            }\n            var body = this.getBody(str, i);","sourceCodeStart":2128,"sourceCodeEnd":2164,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/system/assets/js/framework.js#L2128-L2164","documentation":"Thrown at the end of the object branch of JsonParser.parseString (October CMS AJAX framework). The state machine walks the {..} literal key-by-key (needKey/needBody states, lenient commas, relaxed quotes) and returns only when it places the closing '}'. If the input ends before that brace is produced, the partial result accumulated so far is reported and the parse aborts.","triggerScenarios":"oc.parseJSON(\"{a: 1\") or data-request-data=\"{page: 2, sort: 'name'\" - object literal missing its final }; also inner values left mid-way ({a: ) that consume input without completing the state machine.","commonSituations":"Hand-edited attribute values missing the closing brace; template concatenation dropping the last character; partial JSON pasted into markup; refactors that delete the trailing } while editing the last pair.","solutions":["Append the missing closing '}' to the object literal","Fix any inner incomplete value first - a broken value can consume the real closer","Round-trip the value through oc.parseJSON (or strict JSON.parse) in the console/CI to catch unclosed objects before shipping markup"],"exampleFix":"<!-- before -->\n<div data-request-data=\"{page: 2, sort: 'name'\">...</div>\n\n<!-- after -->\n<div data-request-data=\"{page: 2, sort: 'name'}\">...</div>","handlingStrategy":"try-catch","validationCode":"function objectLiteralCloses(s) {\n  const t = s.trim();\n  if (t[0] !== '{') return true;\n  const closes = (t.match(/}/g) || []).length;\n  const opens = (t.match(/{/g) || []).length;\n  return closes === opens;\n}","typeGuard":null,"tryCatchPattern":"try { const d = oc.parseJSON(raw); } catch (e) { if (/Broken JSON object near/.test(e.message)) console.error('Unterminated { - missing closing brace:', e.message); }","preventionTips":["Every '{' needs its '}' - count them after editing","Fix broken inner values first; they can swallow the closer","Lint attribute JSON in CI with a round-trip parse"],"tags":["json","parser","truncation","html-attribute","frontend"],"backgroundTag":"unterminated-json","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}