laravel/framework · error · RuntimeException

This database driver does not support dropping foreign keys

Error message

This database driver does not support dropping foreign keys by name.

What it means

SQLite cannot drop a foreign key by its constraint name. SQLiteGrammar.compileDropForeign() throws when $command->columns is empty — i.e. dropForeign was called with a constraint name string rather than a column array. When columns ARE provided, SQLite handles it by rebuilding the table. This is a targeted guard, not an unconditional block.

Source

Thrown at src/Illuminate/Database/Schema/Grammars/SQLiteGrammar.php:607

     */
    public function compileDropSpatialIndex(Blueprint $blueprint, Fluent $command)
    {
        throw new RuntimeException('The database driver in use does not support spatial indexes.');
    }

    /**
     * Compile a drop foreign key command.
     *
     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
     * @param  \Illuminate\Support\Fluent  $command
     * @return array
     *
     * @throws \RuntimeException
     */
    public function compileDropForeign(Blueprint $blueprint, Fluent $command)
    {
        if (empty($command->columns)) {
            throw new RuntimeException('This database driver does not support dropping foreign keys by name.');
        }

        // Handled on table alteration...
    }

    /**
     * Compile a rename table command.
     *
     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
     * @param  \Illuminate\Support\Fluent  $command
     * @return string
     */
    public function compileRename(Blueprint $blueprint, Fluent $command)
    {
        $from = $this->wrapTable($blueprint);

        return "alter table {$from} rename to ".$this->wrapTable($command->to);
    }

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Drop the foreign key by columns instead of by name on SQLite: $table->dropForeign(['user_id']).
  2. Driver-guard: if ($conn->getDriverName() === 'sqlite') drop by columns, else drop by name.
  3. Use the anonymous form dropForeign(['user_id']) everywhere — it works on both SQLite and MySQL/Postgres.

Example fix

// before (throws on SQLite when 'fk_orders_user' is a name)
Schema::table('orders', function (Blueprint $table) {
    $table->dropForeign('fk_orders_user');
});

// after (columns work on all drivers)
Schema::table('orders', function (Blueprint $table) {
    $table->dropForeign(['user_id']);
});
Defensive patterns

Strategy: validation

Validate before calling

// Prefer column-array form everywhere — works on SQLite + MySQL/Postgres
$table->dropForeign(['user_id']);

// If you must use names on capable drivers:
if (Schema::getConnection()->getDriverName() !== 'sqlite') {
    $table->dropForeign('fk_orders_user');
}

Prevention

When it happens

Trigger: Calling $table->dropForeign('some_constraint_name') (a name, not columns) on a SQLite connection. The same call works on MySQL/Postgres where constraints are named. SQLite only supports dropping foreign keys by specifying the column(s) involved, because it rebuilds the table.

Common situations: Sharing a migration across MySQL (prod) and SQLite (tests) where dropForeign uses the constraint name; foreign key cleanups generated by schema-diff tools that emit named drops.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/47baab0ed6225bf2.json. Report an issue: GitHub.