Corregir el error «Unknown column ‘updated_at’» en Laravel

Introducción El ORM Eloquent que viene con Laravel te ofrece una forma sencilla de interactuar con tu base de datos. Simplifica todas las operaciones CRUD (create, read, update y delete) y cualquier otra consulta a la base de datos. Tal como indica la documentación oficial de Laravel, Eloquent espera que created_at y updated_at existan

Corregir el error «Unknown column ‘updated_at’» en Laravel
Respuesta rápida

Eloquent escribe created_at y updated_at en cada inserción: el error significa que la tabla no las tiene. Tres soluciones según el caso: añádelas con una migración usando $table->timestamps(), desactívalas con public $timestamps = false; en el modelo, o declara sus nombres reales con las constantes CREATED_AT y UPDATED_AT.

El mensaje salta en el primer save() o create() sobre un modelo:

code
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'INSERT INTO'

La causa es siempre la misma: Eloquent mantiene dos columnas de fecha, created_at y updated_at, y las escribe en cada inserción o actualización. Si la tabla no las tiene, la consulta falla. Hay tres formas de arreglarlo, y la buena depende de la tabla, no de tus preferencias.

Artículo del itinerario Desarrollo web. Error reproducido y soluciones verificadas en Laravel 13.30.1 con MariaDB 11.8.9.

Reconocer el error

El texto cambia según el motor y la operación, pero siempre señala a updated_at o a created_at:

code
-- à l'insertion (MySQL / MariaDB)
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'updated_at' in 'INSERT INTO'

-- à la mise à jour
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'reports.updated_at' in 'SET'

-- sur SQLite
SQLSTATE[HY000]: General error: 1 table reports has no column named updated_at

Comprueba primero qué contiene realmente la tabla:

bash
php artisan tinker --execute='echo implode(", ", Schema::getColumnListing("reports"));'
code
id, title

Si faltan created_at y updated_at, sigue leyendo. Si están pero con otro nombre, ve directamente a la tercera solución.

Solución 1: añadir las columnas

El procedimiento completo está descrito en la guía de migraciones de Laravel.

Es la respuesta correcta en la mayoría de los casos. Saber cuándo se creó y cuándo se modificó una fila acaba sirviendo, tanto para depurar como para ordenar. El helper timestamps() crea las dos columnas de una vez, nullables:

bash
php artisan make:migration add_timestamps_to_reports_table --table=reports
database/migrations/2026_09_02_000000_add_timestamps_to_reports_table.php
public function up(): void
{
    Schema::table('reports', function (Blueprint $table) {
        $table->timestamps();
    });
}

public function down(): void
{
    Schema::table('reports', function (Blueprint $table) {
        $table->dropTimestamps();
    });
}
bash
php artisan migrate

Después de la migración, la inserción pasa y las fechas se rellenan. Verificado: la tabla contiene id, title, created_at, updated_at y $report->created_at devuelve una instancia de Illuminate\Support\Carbon, que puedes formatear y comparar.

En una tabla que ya tiene filas, las columnas se crean a NULL sobre lo existente, y eso no da ningún problema. Si prefieres un valor, decláralo explícitamente:

php
$table->timestamp('created_at')->nullable()->useCurrent();
$table->timestamp('updated_at')->nullable()->useCurrent()->useCurrentOnUpdate();

Solución 2: desactivar los timestamps en el modelo

Cuando la tabla no tiene por qué llevar esas fechas (tabla de enlace, catálogo fijo o esquema impuesto por un sistema externo), díselo al modelo:

app/Models/Video.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Video extends Model
{
    public $timestamps = false;
}

Eloquent deja de rellenar las dos columnas y la inserción funciona. Puedes confirmarlo con $video->usesTimestamps(), que devuelve false.

La misma desactivación se puede hacer puntualmente sobre una instancia, por ejemplo para corregir un dato sin tocar updated_at:

php
$task->timestamps = false;
$task->title = 'Titre corrigé';
$task->save();   // updated_at no cambia
No desactives los timestamps solo para callar el error

Si la tabla debería tener esas columnas, $timestamps = false no arregla nada: quita una información que buscarás más adelante. Reserva esta solución para las tablas donde la fecha de modificación realmente no tiene sentido.

Solución 3: las columnas existen con otro nombre

En una base heredada, las columnas suelen llamarse date_creation, creation_date o modified_on. No hace falta renombrar nada: indícale a Eloquent los nombres reales con dos constantes.

app/Models/Clip.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Clip extends Model
{
    const CREATED_AT = 'creation_date';
    const UPDATED_AT = 'updated_date';
}

A partir de ahí Eloquent escribe en esas columnas. Verificado en Laravel 13: después de Clip::create(['title' => 'Extrait']), la columna creation_date contiene la marca de tiempo y getUpdatedAtColumn() devuelve updated_date.

Si solo existe una de las dos fechas, pon la otra a null:

php
const CREATED_AT = 'creation_date';
const UPDATED_AT = null;   // sin columna de actualización

Los accesores $clip->created_at y $clip->updated_at, en cambio, no siguen estas constantes: devuelven null. Lea la columna por su nombre real, $clip->creation_date, o de forma genérica con $clip->{$clip->getCreatedAtColumn()}.

Qué solución elegir

Situación Solución
Tabla de aplicación normal, columnas simplemente olvidadas Añadir las columnas con una migración
Tabla pivote, catálogo fijo, esquema impuesto public $timestamps = false;
Base heredada con columnas de fecha con otro nombre Constantes CREATED_AT y UPDATED_AT
Una escritura concreta no debe tocar updated_at $model->timestamps = false; antes de save()

Errores frecuentes

Desactivar los timestamps para callar el error En una tabla de aplicación normal, $timestamps = false elimina una información útil en vez de corregir el esquema. Añade las columnas.
Columnas NOT NULL en una tabla ya llena timestamps() las crea nullables, y así pasa. Una definición NOT NULL sin valor por defecto haría fallar la migración.
Renombrar las columnas de la base heredada Innecesario y arriesgado: las constantes CREATED_AT y UPDATED_AT bastan para apuntar a los nombres existentes.
Olvidar UPDATED_AT = null Si la tabla solo tiene columna de creación, dejar UPDATED_AT por defecto vuelve a lanzar el mismo error al actualizar.

EloquentLaravelMigrationsPHP

Damien Flandrin Desarrollador web desde 2010, creador de Gekkode y de Email Impact. Cada artículo se prueba en un proyecto real antes de publicarse. Contacto
Newsletter

Las nuevas pruebas, tutoriales y proyectos, por correo.

Pruebas reproducibles, código versionado, resultados fechados. Nunca spam.