octobercms/october · error · Error

Broken JSON body near ${str}

Error message

Broken JSON body near ${str}

What it means

The catch-all of getBody() in the lenient JSON scanner: the character at the value position matches none of the recognized value starts (quote, t, f, n, digit/+/-/., '{' or '['). Typically an unquoted string value that does not happen to start with t/f/n — the single most common failure when authors write key: value shorthand with text values. The message shows a ~50-character window starting 5 chars before the failure position.

Source

Thrown at modules/system/assets/js/framework.js:2308

              stack.push("[");
            } else if (str[i] === "]") {
              if (stack[stack.length - 1] === "[") {
                stack.pop();
              } else {
                throw new Error("Broken JSON " + (str[pos] === "{" ? "object" : "array") + " body near " + body);
              }
            }
          }
          if (!stack.length) {
            return {
              originLength: i - pos,
              body
            };
          }
        }
        throw new Error("Broken JSON " + (str[pos] === "{" ? "object" : "array") + " body near " + body);
      }
      throw new Error("Broken JSON body near " + str.substr(pos - 5 >= 0 ? pos - 5 : 0, 50));
    }
    canBeKeyHead(ch) {
      if (ch[0] === "\\") return false;
      if (ch[0] >= "a" && ch[0] <= "z" || ch[0] >= "A" && ch[0] <= "Z" || ch[0] === "_") return true;
      if (ch[0] >= "0" && ch[0] <= "9") return true;
      if (ch[0] === "$") return true;
      if (ch.charCodeAt(0) > 255) return true;
      return false;
    }
    isBlankChar(ch) {
      return ch === " " || ch === "\n" || ch === "	";
    }
  };

  // ../../vendor/larajax/larajax/resources/src/core/request-builder.js
  var RequestBuilder = class _RequestBuilder {
    constructor(element, handler, options) {
      this.options = options || {};

View on GitHub (pinned to b608633a7e)

Solutions

  1. Quote all text values: {status: 'active'}.
  2. Lowercase the literals: true / false / null (capitalized variants are treated as unknown tokens).
  3. Remove stray separators (empty value after ':' or ',') — null is allowed as an explicit placeholder.

Example fix

// before
<a data-request="onFilter" data-request-data="status: active">Active</a>

// after
<a data-request="onFilter" data-request-data="{status: 'active'}">Active</a>
Defensive patterns

Strategy: validation

Validate before calling

// Reject capitalized literals and unquoted text values before parsing
function onlyKnownBareValues(value) {
    var bare = value.replace(/'[^']*'|"[^"]*"/g, '');
    return bare.match(/:(?:\s*)(True|False|Null|undefined)\b/) === null &&
           bare.match(/:(?:\s*)(?!true\b|false\b|null\b|-?[\d.+-])[^\s,}\]\d"'][^,}\]]*/) === null;
}

Prevention

When it happens

Trigger: data-request-data="status: active" (wrapped to {status: active}, the 'a' is unrecognized); {ok: True} / {v: False} / {x: Null} — capitalized literals; {a: undefined}; a stray comma or colon in value position ({a: , b: 1}).

Common situations: Shorthand attribute configs with unquoted text values (the classic mistake — only true/false/null and numbers may be bare); booleans capitalized by habit from other languages; values copied from PHP ('True') into frontend attributes.

Related errors


AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21). Data as JSON: /api/errors/01704674e8933214. Report an issue: GitHub.