laravel/framework · error · RuntimeException
SQLite does not support altering primary keys.
Error message
SQLite does not support altering primary keys.
What it means
SQLiteGrammar.compileRenameIndex() throws RuntimeException when the matched index is a PRIMARY KEY. SQLite's primary keys are tied to the table's rowid and cannot be altered via the drop+recreate rename path the grammar uses for normal indexes. This fires AFTER the index lookup succeeds but identifies it as primary.
Source
Thrown at src/Illuminate/Database/Schema/Grammars/SQLiteGrammar.php:647
*
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Illuminate\Support\Fluent $command
* @return array
*
* @throws \RuntimeException
*/
public function compileRenameIndex(Blueprint $blueprint, Fluent $command)
{
$indexes = $this->connection->getSchemaBuilder()->getIndexes($blueprint->getTable());
$index = Arr::first($indexes, fn ($index) => $index['name'] === $command->from);
if (! $index) {
throw new RuntimeException("Index [{$command->from}] does not exist.");
}
if ($index['primary']) {
throw new RuntimeException('SQLite does not support altering primary keys.');
}
if ($index['unique']) {
return [
$this->compileDropUnique($blueprint, new IndexDefinition(['index' => $index['name']])),
$this->compileUnique($blueprint,
new IndexDefinition(['index' => $command->to, 'columns' => $index['columns']])
),
];
}
return [
$this->compileDropIndex($blueprint, new IndexDefinition(['index' => $index['name']])),
$this->compileIndex($blueprint,
new IndexDefinition(['index' => $command->to, 'columns' => $index['columns']])
),
];
}View on GitHub (pinned to bd6b5437e6)
Solutions
- Do not rename a primary key index on SQLite — leave primary keys as-is or recreate the table with the new constraint.
- If a rename is essential, build a new table with the desired primary key, copy data, and swap (SQLite table-rebuild pattern).
- Skip the rename for SQLite via a driver guard and only rename on drivers that permit it.
Example fix
// before (throws on SQLite)
Schema::table('users', function (Blueprint $table) {
$table->renameIndex('users_pkey', 'users_pk');
});
// after — skip on SQLite, rebuild table if rename is required
Schema::table('users', function (Blueprint $table) {
if ($table->getConnection()->getDriverName() !== 'sqlite') {
$table->renameIndex('users_pkey', 'users_pk');
}
}); Defensive patterns
Strategy: validation
Validate before calling
if (Schema::getConnection()->getDriverName() !== 'sqlite') {
$table->renameIndex('users_pkey', 'users_pk');
} Prevention
- Never attempt to rename a primary-key index on SQLite.
- If a primary key rename is required on SQLite, rebuild the table.
- Driver-guard primary-key rename migrations.
When it happens
Trigger: Calling $table->renameIndex('users_pkey', 'users_id_new') (or the auto-generated primary index name) on a SQLite connection. The lookup finds the index but $index['primary'] is true, so SQLite refuses the rename.
Common situations: Renaming what is actually a primary key index; sharing rename migrations between drivers (Postgres/MySQL allow renaming primary indexes in some forms); schema-diff tools emitting primary-index renames.
Related errors
- The database driver in use does not support spatial indexes.
- This database driver does not support dropping foreign keys
- Index [{$command->from}] does not exist.
- This database driver requires a type, see the virtualAs / st
- This database driver does not support modifying columns.
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/9b52e753fe9d8804.json.
Report an issue: GitHub.