laravel/framework · error · LogicException
This database driver does not support modifying generated…
Error message
This database driver does not support modifying generated columns.
What it means
PostgresGrammar::modifyVirtualAs throws a LogicException when a column is being modified ($column->change is true) AND a non-null virtualAs attribute is present. PostgreSQL cannot ALTER a generated VIRTUAL expression in place; you must drop and recreate the column. Setting virtualAs back to null is allowed (it emits 'drop expression if exists'), but providing a new expression on a change is not.
Solutions
- Drop the virtualAs attribute when calling ->change() for unrelated modifications: $table->integer('col')->change() without virtualAs.
- To change the expression, split into two migrations: drop the column (or drop expression), then re-add it with the new virtualAs.
- If the intent was to remove the generation expression, call ->virtualAs(null)->change() which emits 'drop expression if exists'.
Example fix
// before
$table->integer('total')->virtualAs('a + b')->change();
// after (replace the expression)
// migration 1
Schema::table('orders', fn (Blueprint $t) => $t->dropColumn('total'));
// migration 2
Schema::table('orders', fn (Blueprint $t) => $t->integer('total')->virtualAs('a + b + fee')); Defensive patterns
Strategy: validation
Validate before calling
// when modifying a column on Postgres, do NOT resend virtualAs unless you mean to drop it
$col = $table->integer('total');
if (! $columnWantsNewExpression) {
// just change another attribute
$col->nullable(false)->change();
} else {
// to remove the expression:
$col->virtualAs(null)->change();
} Prevention
- Split generated-column expression changes into drop + re-add migrations on Postgres.
- When calling ->change(), only set the attributes you intend to alter.
- Use ->virtualAs(null)->change() to drop an expression, never a new expression.
When it happens
Trigger: Using $table->integer('col')->virtualAs('expr')->change() (i.e. a column modification that supplies a non-null virtualAs) on a Postgres connection.
Common situations: Calling ->change() on a migration that also redefines the generation expression; trying to repoint a generated column at a new formula in a Postgres-only deploy; migration scaffolding tools that always resend all attributes on change.
Related errors
- This database driver does not support the tsvector type.
- This database driver requires a type, see the virtualAs /…
- This database driver requires a type, see the virtualAs /…
- SQLite does not support altering primary keys.
- The database driver in use does not support spatial indexes.
AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11).
Data as JSON: /api/errors/58de220de6e5dbee.
Report an issue: GitHub.
Appendix: source
Thrown at src/Illuminate/Database/Schema/Grammars/PostgresGrammar.php:1283
}
}
/**
* Get the SQL for a generated virtual column modifier.
*
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Illuminate\Support\Fluent $column
* @return string|null
*
* @throws \LogicException
*/
protected function modifyVirtualAs(Blueprint $blueprint, Fluent $column)
{
if ($column->change) {
if (array_key_exists('virtualAs', $column->getAttributes())) {
return is_null($column->virtualAs)
? 'drop expression if exists'
: throw new LogicException('This database driver does not support modifying generated columns.');
}
return null;
}
if (! is_null($column->virtualAs)) {
return " generated always as ({$this->getValue($column->virtualAs)}) virtual";
}
}
/**
* Get the SQL for a generated stored column modifier.
*
* @param \Illuminate\Database\Schema\Blueprint $blueprint
* @param \Illuminate\Support\Fluent $column
* @return string|null
*
* @throws \LogicExceptionView on GitHub (pinned to e0f6eb3518)