{"record":{"id":"2d06027bc52ddb4f","repo":"octobercms/october","slug":"broken-json-object","errorCode":null,"errorMessage":"Broken JSON object.","messagePattern":"Broken JSON object\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"modules/system/assets/js/framework.js","lineNumber":2062,"sourceCode":"        return value;\n      }\n      if (value.charAt(0) !== \"{\") {\n        value = \"{\" + value + \"}\";\n      }\n      try {\n        return this.parseJSON(value);\n      } catch (e) {\n        throw new Error(\"Error parsing the \" + name + \" attribute value. \" + e);\n      }\n    }\n    static parseJSON(json) {\n      return JSON.parse(new _JsonParser().parseString(json));\n    }\n    // Private\n    parseString(str) {\n      str = str.trim();\n      if (!str.length) {\n        throw new Error(\"Broken JSON object.\");\n      }\n      var result = \"\";\n      while (str && str[0] === \",\") {\n        str = str.substr(1);\n      }\n      if (str[0] === '\"' || str[0] === \"'\") {\n        if (str[str.length - 1] !== str[0]) {\n          throw new Error(\"Invalid string JSON object.\");\n        }\n        var body = '\"';\n        for (var i = 1; i < str.length; i++) {\n          if (str[i] === \"\\\\\") {\n            if (str[i + 1] === \"'\") {\n              body += str[i + 1];\n            } else {\n              body += str[i];\n              body += str[i + 1];\n            }","sourceCodeStart":2044,"sourceCodeEnd":2080,"githubUrl":"https://github.com/octobercms/october/blob/b608633a7e8922487d91a8161499020121c3b3bf/modules/system/assets/js/framework.js#L2044-L2080","documentation":"Thrown at the top of JsonParser.parseString (October CMS AJAX framework) when the input, after trimming, is empty. The lenient parser (oc.parseJSON) refuses empty strings because there is no JSON value to produce; attribute helpers usually brace-wrap empty values into '{}' before parsing, so this surfaces mainly on direct oc.parseJSON('') calls.","triggerScenarios":"oc.parseJSON('') or oc.parseJSON('   ') called directly; code doing oc.parseJSON(el.getAttribute('x')) where the attribute is absent (null coerces oddly) or blank; feeding a wiped-out variable into the parser.","commonSituations":"Dynamic values that can be empty by design (empty filter state) piped straight into parseJSON; getAttribute returning null/'' for a missing attribute; AJAX payloads whose data field is empty and then re-parsed.","solutions":["Skip parsing when the input is blank: if (!raw || !raw.trim()) return defaultValue","Default missing attributes: oc.parseJSON(el.getAttribute('x') || '{}')","Guard upstream so empty state produces '{}' instead of ''"],"exampleFix":"// before\nconst data = oc.parseJSON(input.value);\n\n// after\nconst data = oc.parseJSON(input.value.trim() || '{}');","handlingStrategy":"validation","validationCode":"function parseOr(raw, fallback) {\n  const s = (raw ?? '').trim();\n  return s ? oc.parseJSON(s) : fallback;\n}\n\nconst data = parseOr(input.value, {});","typeGuard":"const isNonEmptyJsonText = (s) => typeof s === 'string' && s.trim().length > 0;","tryCatchPattern":"try { const d = oc.parseJSON(raw); } catch (e) { if (/Broken JSON object\\./.test(e.message)) { /* empty input - use default */ } }","preventionTips":["Default blank inputs to '{}' before parsing","Coerce missing attributes: el.getAttribute('x') || '{}'","Treat empty state as a valid case in your data flow, not as parse input"],"tags":["json","ajax","parser","empty-input","frontend"],"backgroundTag":"empty-json-input","analyzedSha":"b608633a7e8922487d91a8161499020121c3b3bf","analyzedAt":"2026-08-21T04:24:57.515Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}