laravel/framework · error · RuntimeException
SQLite does not support altering primary keys.
Error message
SQLite does not support altering primary keys.
What it means
compileRenameIndex refuses to rename a PRIMARY KEY index on SQLite. SQLite has no ALTER statement to drop or replace a primary key definition, and renameIndex implements rename-by-drop-and-recreate, which is impossible for primaries. The guard fires after the source index is located, when $index['primary'] is true.
Solutions
- Exclude primary indexes from rename operations on SQLite (gate renameIndex by $index['primary'] === false using getIndexes()).
- If the primary must be renamed, recreate the table with the new primary definition (SQLite only supports table-rebuild for primary-key changes).
- Run the rename against Postgres/MySQL where primary keys can be dropped and re-added.
Example fix
// before
$table->renameIndex('users_pkey', 'users_id_primary');
// after (skip primaries on SQLite)
use Illuminate\Support\Facades\DB;
$index = collect(DB::connection()->getSchemaBuilder()->getIndexes('users'))
->firstWhere('name', 'users_pkey');
if ($index && ! $index['primary']) {
$table->renameIndex('users_pkey', 'users_id_primary');
} Defensive patterns
Strategy: validation
Validate before calling
use Illuminate\Support\Facades\DB;
$index = collect(DB::connection()->getSchemaBuilder()->getIndexes('users'))
->firstWhere('name', 'users_pkey');
if ($index && ! $index['primary']) {
$table->renameIndex('users_pkey', 'users_id_primary');
} Type guard
function indexIsRenamable(string $table, string $name): bool {
$i = collect(\Illuminate\Support\Facades\DB::connection()->getSchemaBuilder()->getIndexes($table))
->firstWhere('name', $name);
return $i !== null && ! $i['primary'];
} Prevention
- Exclude primary indexes from rename logic, especially in driver-portable migrations.
- On SQLite, recreate the table to change a primary key rather than renameIndex.
- Filter getIndexes() by primary/unique flags before calling renameIndex.
When it happens
Trigger: Calling $table->renameIndex('sqlite_autoindex_...', 'new_name') (or the named primary key) on a SQLite table where the matched index is a primary key.
Common situations: Generic rename migrations that iterate over all indexes including primaries; renaming the implicit primary index created by $table->id(); cross-database migrations that name the primary on Postgres/MySQL but hit SQLite in tests.
Related errors
- Index [ ] does not exist.
- The database driver in use does not support spatial indexes.
- This database driver does not support dropping foreign keys…
- This database driver requires a type, see the virtualAs /…
- This database driver does not support modifying generated…
AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11).
Data as JSON: /api/errors/9b52e753fe9d8804.
Report an issue: GitHub.
Appendix: 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 e0f6eb3518)