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

  1. Pass the SQL expression as a single string: 'generated' => "CONCAT(first_name, ' ', last_name)".
  2. Join list-form expressions first: implode(', ', $parts).
  3. 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

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


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/055431307ac7aa5c. Report an issue: GitHub.