Common causes
- A typo or different spelling than the real column name
- Code was deployed but the migration that adds the column was not run on this database
- A string value wrapped in backticks or double quotes (with ANSI_QUOTES) so MySQL reads it as a column name
- Using a SELECT alias in WHERE, which MySQL evaluates before the alias exists
- Laravel/Eloquent writing created_at or updated_at to a table without timestamp columns
- Connecting to a different database or table prefix than expected, such as a staging copy
How to fix it
- List the real columns. Run SHOW COLUMNS FROM users; or DESCRIBE users; on the same connection your app uses. Compare the names exactly, including underscores.
- Confirm the database and prefix. Run SELECT DATABASE(); and check the table prefix in your config. A query that works locally can fail because production points at an older schema.
- Run pending migrations. Apply the schema change: php artisan migrate, bin/console doctrine:migrations:migrate, or the ALTER TABLE your release needs. Then retry the query.
- Fix quotes around values. Use single quotes for strings and backticks only for identifiers: WHERE status = 'active', not WHERE status = `active`. Prepared statements avoid this entirely.
- Move aliases out of WHERE. Repeat the expression in WHERE or filter the alias in HAVING or an outer query. MySQL allows aliases in GROUP BY, HAVING and ORDER BY but not in WHERE.
- Add the column if it is truly needed. Run ALTER TABLE users ADD COLUMN email VARCHAR(255) NULL; after taking a backup. For Eloquent models without timestamps set public $timestamps = false;.
SQL
SHOW COLUMNS FROM users;
-- wrong: backticks make 'active' a column name
SELECT id FROM users WHERE status = `active`;
-- right
SELECT id FROM users WHERE status = 'active';
-- add a missing column (after a backup)
ALTER TABLE users ADD COLUMN email VARCHAR(255) NULL; How to stop it happening again
- Ship schema migrations with the code that depends on them and run them in deployment
- Use prepared statements so values are never written as identifiers
- Keep a schema dump in version control and diff it between environments
- Test queries against a database built from migrations, not a hand-edited copy