phalcon/cphalcon · error · InvalidGenerationExpression
Column generation expression must be a string
Error message
Column generation expression must be a string
What it means
Phalcon\Db\Column supports generated (computed) columns via definition['generated']. When the value is non-null it must be a string holding the SQL generation expression; any other PHP type (array, int, bool) throws InvalidGenerationExpression. null itself is allowed and simply means 'not generated'.
Source
Thrown at phalcon/Db/Column.zep:726
let this->bindType = bindType;
}
/**
* Get the column comment
*/
if fetch comment, definition["comment"] {
let this->comment = comment;
}
/**
* Generated/computed column expression. When a non-empty string is
* provided the column is marked as generated and DEFAULT /
* AUTO_INCREMENT are no longer compatible at the dialect level.
*/
if fetch generated, definition["generated"] {
if generated !== null {
if unlikely typeof generated != "string" {
throw new InvalidGenerationExpression();
}
if unlikely this->autoIncrement {
throw new GeneratedAutoIncrementConflict();
}
if unlikely this->defaultValue !== null {
throw new GeneratedDefaultConflict();
}
let this->generated = generated;
}
}
/**
* Storage flag for generated columns. true = STORED, false = VIRTUAL.
*/
if fetch generationStored, definition["generationStored"] {View on GitHub (pinned to b7419de9cd)
Solutions
- Pass the SQL expression as a single string: 'generated' => "CONCAT(first_name, ' ', last_name)".
- Join list-form expressions first: implode(', ', $parts).
- Do not use 'generated' as a boolean marker - it carries the expression text itself.
Example fix
// before
$column = new Column('full_name', [
'type' => Column::TYPE_VARCHAR,
'size' => 255,
'generated' => ['first_name', 'last_name'], // throws InvalidGenerationExpression
]);
// after
$column = new Column('full_name', [
'type' => Column::TYPE_VARCHAR,
'size' => 255,
'generated' => "CONCAT(first_name, ' ', last_name)",
]); Defensive patterns
Strategy: type-guard
Validate before calling
if (isset($definition['generated'])
&& $definition['generated'] !== null
&& !is_string($definition['generated'])) {
throw new InvalidArgumentException('"generated" must be a SQL expression string');
}
$column = new Column('full_name', $definition); Type guard
function generatedExpressionIsString(array $definition): bool
{
return !isset($definition['generated'])
|| $definition['generated'] === null
|| is_string($definition['generated']);
} Prevention
- Treat 'generated' as expression text, never a boolean or a list.
- Implode array-shaped expressions at the config boundary.
- Document the generated-column contract in your schema DSL.
When it happens
Trigger: new Column('full', ['type' => Column::TYPE_VARCHAR, 'generated' => ['first', 'last']]); passing an expression list instead of a pre-joined string; using true as a boolean marker for 'this column is generated'; numeric expression fragments from JSON.
Common situations: Config schemas expressing generated expressions as lists that were never implode()d; wrappers passing definition arrays verbatim from JSON; misunderstanding the key as a boolean flag rather than the expression text.
Related errors
- Generated column cannot also be auto-increment
- Generated column cannot have a default value
- CHECK expression must be a non-empty string
- Column type is required
- Column type does not support scale parameter
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/055431307ac7aa5c.
Report an issue: GitHub.