laravel/framework · error · LogicException
This database driver does not support modifying generated co
Error message
This database driver does not support modifying generated columns.
What it means
PostgreSQL cannot ALTER a generated virtual column to a new expression; it can only drop the expression. modifyVirtualAs() throws LogicException specifically when a change-modify operation ($column->change === true) supplies a non-null virtualAs value. Passing virtualAs(null) is allowed and emits 'drop expression if exists'.
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 bd6b5437e6)
Solutions
- Drop the existing generated column and recreate it with the new expression instead of using change().
- If you only want to remove the expression, call ->virtualAs(null)->change() which emits 'drop expression if exists'.
- Move the expression into a view or a generated-as-identity approach if frequent changes are expected.
- Confirm the target driver: this works on MySQL but not Postgres — split driver-specific migrations.
Example fix
// before (throws on Postgres)
Schema::table('orders', function (Blueprint $table) {
$table->integer('total')->virtualAs('price * qty')->change();
});
// after (drop then recreate)
Schema::table('orders', function (Blueprint $table) {
$table->integer('total')->virtualAs(null)->change(); // drop expression
});
Schema::table('orders', function (Blueprint $table) {
$table->integer('total')
->virtualAs('price * qty + tax')
->change();
});
// cleanest: dropColumn + add the column fresh Defensive patterns
Strategy: validation
Validate before calling
// On Postgres, never change() a non-null virtualAs
if (Schema::getConnection()->getDriverName() === 'pgsql') {
// drop the column and re-add it instead of ->change()
} Prevention
- Postgres cannot modify generated expressions — only drop them via ->virtualAs(null)->change().
- For formula changes, dropColumn then re-add the generated column.
- Driver-split migrations that change generated columns.
When it happens
Trigger: Using $table->string('col')->virtualAs('new_expr')->change() in a Postgres migration — i.e. trying to update an existing generated column's expression via the change() modifier. The same call with virtualAs(null)->change() succeeds (drops the expression).
Common situations: Refactoring a generated column's formula in Postgres; running a migration that worked on MySQL (which permits modifying generated columns) against a Postgres database; auto-sync tools that diff columns and try to change the expression.
Related errors
- This database driver does not support the computed type.
- This database driver does not support the vector type.
- This database driver does not support the tsvector type.
- This database driver requires a type, see the virtualAs / st
- This database driver requires a type, see the virtualAs / st
AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06).
Data as JSON: /data/errors/58de220de6e5dbee.json.
Report an issue: GitHub.