knex/knex · error · Error

Parsing CREATE INDEX failed at [${result.input.slice(result.

Error message

Parsing CREATE INDEX failed at [${result.input.slice(result.index).map((t) => t.text).join(' ')}] of "${sql}"

What it means

Same parser infrastructure as CREATE TABLE, but for CREATE INDEX statements. When rebuilding a table knex must re-create its indexes, so it parses each existing CREATE INDEX. If the index DDL uses syntax the parser rejects (partial-index WHERE clauses with unsupported operators, expression indexes with complex expressions, collations, etc.), parsing fails with the unparsed remainder and original SQL.

Source

Thrown at lib/dialects/sqlite3/schema/internal/parser.js:35

  const result = createTable({ input: tokenize(sql, TOKENS) });

  if (!result.success) {
    throw new Error(
      `Parsing CREATE TABLE failed at [${result.input
        .slice(result.index)
        .map((t) => t.text)
        .join(' ')}] of "${sql}"`
    );
  }

  return result.ast;
}

function parseCreateIndex(sql) {
  const result = createIndex({ input: tokenize(sql, TOKENS) });

  if (!result.success) {
    throw new Error(
      `Parsing CREATE INDEX failed at [${result.input
        .slice(result.index)
        .map((t) => t.text)
        .join(' ')}] of "${sql}"`
    );
  }

  return result.ast;
}

function createTable(ctx) {
  return s(
    [
      t({ text: 'CREATE' }, (v) => null),
      temporary,
      t({ text: 'TABLE' }, (v) => null),
      exists,
      schema,

View on GitHub (pinned to e25d54bcb7)

Solutions

  1. Drop and recreate the problematic index using a parser-compatible CREATE INDEX before running the alter.
  2. Perform the table alter manually with raw SQL so knex's index parser is bypassed.
  3. Simplify the index definition (plain column indexes, simple WHERE clauses) and upgrade knex for broader coverage.

Example fix

// before
await knex.schema.alterTable('t', (b) => b.setNullable('c'));
// index was: CREATE INDEX i ON t (lower(name)) WHERE active = 1;
// after
await knex.raw('DROP INDEX i');
await knex.schema.alterTable('t', (b) => b.setNullable('c'));
await knex.raw('CREATE INDEX i ON t (lower(name)) WHERE active = 1');
Defensive patterns

Strategy: try-catch

Validate before calling

const { parseCreateIndex } = require('knex/lib/dialects/sqlite3/schema/internal/parser');
async function assertIndexesParsable(knex, table) {
  const rows = await knex.raw(`select sql from sqlite_master where type='index' and tbl_name=?`, [table]);
  for (const r of rows) {
    if (!r.sql) continue;
    try { parseCreateIndex(r.sql); } catch (e) { throw new Error(`Index DDL not parser-compatible: ${r.sql}`); }
  }
}

Try / catch

try {
  await knex.schema.alterTable('t', (b) => b.setNullable('c'));
} catch (e) {
  if (/Parsing CREATE INDEX failed/i.test(e.message)) {
    // drop/recreate the offending index manually, or perform raw alter
  } else throw e;
}

Prevention

When it happens

Trigger: Any table-rebuild DDL op (dropColumn, setNullable, dropForeign, etc.) on a table that has an index whose CREATE INDEX statement exceeds the parser's coverage. The error surfaces during the index-recreate phase of the rebuild.

Common situations: Indexes created via raw SQL with features beyond knex's parser. Expression indexes with functions or operators the parser grammar doesn't handle. Partial indexes with complex predicates.

Related errors


AI-assisted analysis of knex/knex@e25d54bcb7 (2026-08-03). Data as JSON: /data/errors/035310c434cb5071.json. Report an issue: GitHub.