sequelize/sequelize · error · TypeError

Failed to parse syntax of json path. Parse error at index ${

Error message

Failed to parse syntax of json path. Parse error at index ${parsed.ref.start.index}:
${code}
${' '.repeat(parsed.ref.start.index)}^

What it means

parseJsonPropertyKeyInternal parses the nested-JSON key syntax (a subset of the attribute syntax used inside JSON columns). When the key violates the partialJsonPath grammar — allowed forms are bare keys, double-quoted keys, and `[index]` access plus optional `::cast`/`:modifier` — Sequelize throws a TypeError with a caret at the failing index.

Source

Thrown at packages/core/src/utils/attribute-syntax.ts:271

        >,
      ]
    >,
    castOrModifiers: UselessNode<
      'castOrModifiers?',
      [
        UselessNode<
          'castOrModifiers',
          [UselessNode<'(...)+', Array<StringNode<'cast' | 'modifier'>>>]
        >,
      ]
    >,
  ];
}

function parseJsonPropertyKeyInternal(code: string): ParsedJsonPropertyKey {
  const parsed = attributeParser.parse(code, false, 'partialJsonPath') as JsonPathAst | ParseError;
  if (parsed instanceof ParseError) {
    throw new TypeError(`Failed to parse syntax of json path. Parse error at index ${parsed.ref.start.index}:
${code}
${' '.repeat(parsed.ref.start.index)}^`);
  }

  const [firstKey, jsonPathNodeRaw, castOrModifiersNodeRaw] = parsed.value;

  const pathSegments: Array<string | number> = [parseJsonPathSegment(firstKey)];

  const jsonPathNodes = jsonPathNodeRaw.value[0]?.value[0].value;
  if (jsonPathNodes) {
    for (const pathNode of jsonPathNodes) {
      pathSegments.push(parseJsonPathSegment(pathNode));
    }
  }

  const castOrModifierNodes = castOrModifiersNodeRaw.value[0]?.value[0].value;
  const castsAndModifiers: Array<string | Class<DialectAwareFn>> = [];

View on GitHub (pinned to 7e1deec499)

Solutions

  1. Use double quotes around keys with special characters: `'json."weird key".sub'`.
  2. Use `[n]` for numeric index access and single dots between segments.
  3. Validate/escape dynamic path segments before assembling the key; prefer sequelize.jsonPath if available for untrusted paths.
  4. Read the caret line in the error to locate the exact bad index.

Example fix

// before
Model.findAll({ where: { 'meta.nested..deep': value } }); // bad double dot

// after
Model.findAll({ where: { 'meta.nested.deep': value } });
Defensive patterns

Strategy: validation

Validate before calling

const JSON_KEY_RE = /^(?:"(?:[^"\\]|\\.)+"|[A-Za-z_][\w-]*|\d+)(?:\.(?:"(?:[^"\\]|\\.)+"|[A-Za-z_][\w-]*|\d+)|\[\d+\])*(?:::[A-Za-z_]\w*|:[A-Za-z_]\w*)*$/;
function isValidJsonPathKey(key) {
  return JSON_KEY_RE.test(key);
}
if (!isValidJsonPathKey(userKey)) throw new TypeError(`Invalid json path key: ${userKey}`);

Type guard

function isValidJsonPathKey(key: string): boolean {
  return /^(?:"(?:[^"\\]|\\.)+"|[A-Za-z_][\w-]*|\d+)(?:\.(?:"(?:[^"\\]|\\.)+"|[A-Za-z_][\w-]*|\d+)|\[\d+\])*(?:::[A-Za-z_]\w*|:[A-Za-z_]\w*)*$/.test(key);
}

Try / catch

try {
  await Model.findAll({ where: { [jsonKey]: val } });
} catch (e) {
  if (/Failed to parse syntax of json path/.test(e.message)) {
    // rebuild path with quoted segments or use sequelize.jsonPath
  } else throw e;
}

Prevention

When it happens

Trigger: Querying a JSON column with a malformed nested key such as `'$nested..deep'`, `'data[]'` (empty index), `'json::'` (empty cast), or an unquoted key with characters outside [A-Za-z0-9_-] (use double quotes for those).

Common situations: Building JSON path keys from user input without escaping; assuming arbitrary characters are allowed in path segments; mixing the association `$...$` syntax into a JSON-only context; v6 code that relied on looser parsing.

Related errors


AI-assisted analysis of sequelize/sequelize@7e1deec499 (2026-08-03). Data as JSON: /data/errors/d11a99f3f2b3f82d.json. Report an issue: GitHub.