yiisoft/yii2 · error · yii\db\Exception

Unable to find column '$oldName' in table '$table'.

Error message

Unable to find column '$oldName' in table '$table'.

What it means

yii\db\mysql\QueryBuilder::renameColumn() (framework/db/mysql/QueryBuilder.php:80-...) runs SHOW CREATE TABLE to preserve the column's exact definition when emitting ALTER TABLE ... CHANGE. The exception fires when that query returns no row — meaning the table itself does not exist or is unreadable — even though the message blames the column ('Unable to find column X'). Reached via yii\db\Command::renameColumn() (framework/db/Command.php:746) and Migration::renameColumn() (framework/db/Migration.php:414), so migrations are the usual place it appears.

Source

Thrown at framework/db/mysql/QueryBuilder.php:85

        return array_merge(parent::defaultExpressionBuilders(), [
            'yii\db\JsonExpression' => 'yii\db\mysql\JsonExpressionBuilder',
        ]);
    }

    /**
     * Builds a SQL statement for renaming a column.
     * @param string $table the table whose column is to be renamed. The name will be properly quoted by the method.
     * @param string $oldName the old name of the column. The name will be properly quoted by the method.
     * @param string $newName the new name of the column. The name will be properly quoted by the method.
     * @return string the SQL statement for renaming a DB column.
     * @throws Exception
     */
    public function renameColumn($table, $oldName, $newName)
    {
        $quotedTable = $this->db->quoteTableName($table);
        $row = $this->db->createCommand('SHOW CREATE TABLE ' . $quotedTable)->queryOne();
        if ($row === false) {
            throw new Exception("Unable to find column '$oldName' in table '$table'.");
        }
        if (isset($row['Create Table'])) {
            $sql = $row['Create Table'];
        } else {
            $row = array_values($row);
            $sql = $row[1];
        }
        if (preg_match_all('/^\s*[`"](.*?)[`"]\s+(.*?),?$/m', $sql, $matches)) {
            foreach ($matches[1] as $i => $c) {
                if ($c === $oldName) {
                    return "ALTER TABLE $quotedTable CHANGE "
                        . $this->db->quoteColumnName($oldName) . ' '
                        . $this->db->quoteColumnName($newName) . ' '
                        . $matches[2][$i];
                }
            }
        }
        // try to give back a SQL anyway

View on GitHub (pinned to 66f00d18a2)

Solutions

  1. Verify the table first: if ($this->db->getTableSchema($table) === null) throw a clear exception
  2. Check migration state with ./yii migrate/history and apply missing base migrations
  3. Confirm the migration targets the right connection: var_dump($this->db->dsn) or set the migration component explicitly

Example fix

// before
public function safeUp()
{
    $this->renameColumn('user_profile', 'name', 'full_name'); // table missing -> Exception
}

// after
public function safeUp()
{
    if ($this->db->getTableSchema('user_profile') === null) {
        throw new \yii\console\Exception('Table user_profile does not exist — apply earlier migrations first.');
    }
    $this->renameColumn('user_profile', 'name', 'full_name');
}
Defensive patterns

Strategy: validation

Validate before calling

if ($this->db->getTableSchema($table) === null) {
    throw new \yii\console\Exception("Table '$table' does not exist — apply earlier migrations first.");
}
$this->renameColumn($table, $oldName, $newName);

Try / catch

try {
    $this->renameColumn($table, $oldName, $newName);
} catch (\yii\db\Exception $e) {
    // SHOW CREATE TABLE returned no row — verify table name and connection
    \Yii::error('renameColumn failed: ' . $e->getMessage(), __METHOD__);
    throw $e;
}

Prevention

When it happens

Trigger: $this->renameColumn('usr','name','full_name') in a migration where the table name is misspelled or the table was never created (earlier migration failed); renaming a column in the same migration before createTable(); the migration component bound to a different DB connection than the one holding the table.

Common situations: Migration chains reordered/squashed so renameColumn runs before the table exists; multi-connection apps where $this->db points at the wrong database; environments where a prior migration failed silently.

Related errors


AI-assisted analysis of yiisoft/yii2@66f00d18a2 (2026-08-17). Data as JSON: /api/errors/f02104aeae726f81. Report an issue: GitHub.