Framework: Invalid default value for 'created_at'

Created on 19 Feb 2014  Â·  72Comments  Â·  Source: laravel/framework

I was getting this error when using $table->timestamps() in a migration:

SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'created_at' (SQL: create table vehicles (id int unsigned not null auto_increment primary key, name varchar(255) not null, code varchar(255) not null, description text not null, capacity int not null, company_id int not null, created_at timestamp default 0 not null, updated_at timestamp default 0 not null) default character set utf8 collate utf8_unicode_ci)

with a MySQL backend. Turns out it's because I had NO_ZERO_DATE enabled. This actually makes sense though: created_at should either always contain a valid date, or it needs to be nullable. 0 does not make sense.

I think a more sensible default is this:

public function timestamps()
{
    $this->timestamp('created_at')->default(DB::raw('CURRENT_TIMESTAMP'));
    $this->timestamp('updated_at')->default(DB::raw('CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP'));
}

But it only works on MySql 5.6+, I believe (you're only allowed one CURRENT_TIMESTAMP prior to that, for whatever reason). In which case maybe we should make created_at default to CURRENT_TIMESTAMP and updated_at be nullable? I'm just starting to learn Laravel, I'm not sure if updated_at is intended to start out blank and be updated after the first modify, or always contain a value.

Most helpful comment

Ah, I have found the issue a fix, probably.

My "old" database.php config file does not have strict set to false ('strict' => false) as laravel/laravel does. When I add that line to the mysql config, all migrations work just fine (in my case)...

Edit: I noticed it doesn't matter what the value of strict is, as long as it's present it won't fail (checked on clean Laravel install).

All 72 comments

I believe it was set to something like that back in some version of the beta or pre-beta but I think it created more problems than it solved, and that's why we ended up with the current version

As of now all the handling and logic controlling how and when the updated_at column is updated is now controlled in php code. So I think there are a lot of places in need of rewrite if this is changed.
For example to get the ability to update a row without updating the updated_at you either need to change the table, temporarily removing the _on update_ clause or maybe setting the updated_at=updated_at will override the _on update_. Not sure if the latter will work.

Hrm... would it be possible to give a better warning at least? I probably never would have figured it out if I didn't stumble across this blog post in Japanese. If not in artisan, at least in the Quickstart Tutorial which I was having a heck of a time following along with :-)

@mnbayazit if you have a suggestion for improving the docs, you could always fork them, make your edits and issue a pull request :)

This is due to MySQL not accepting zero as a valid defalt date and thus the table creation fails a constraint check on creation.

You probably have NO_ZERO_DATE enabled in your MySQL configuration. Setting this to off will allow you to create the table (or alternatively remove the default 0 value or change it to CURRENT_TIMESTAMP.

@kingpabel Did you read my initial post? That's exactly what I said. Disabling NO_ZERO_DATE is not a good solution - dates should never be 0, why would I allow it?

Only way to properly fix is to override the blue print class and fix the timestamps() method. I don't know why Laravel's default behavior is to punish us for using strict settings.

I also encountered this issue. I'm thinking about using:

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

Instead of $table->timestamps();

What do you guys think?

The issue popped up again with the newest version of Homestead. I guess the new version of MySQL shipped with it has different settings than in previous Homestead versions.

Are you inserting records with no time stamp?

On Sun, Nov 15, 2015 at 5:45 AM, Michaël Lecerf [email protected]
wrote:

The issue popped up again with the newest version of Homestead. I guess the new version of MySQL shipped with it has different settings than in previous Homestead versions.

Reply to this email directly or view it on GitHub:
https://github.com/laravel/framework/issues/3602#issuecomment-156806583

The exception is thrown when creating the table itself, before inserting any data.
This happens because the default value for timestamp fields is set to be 0.

Example of a crashing migration:

// ...

public function up()
{
    Schema::create('users', function(Blueprint $table)
    {
        $table->increments('id');
        $table->string('email')->unique()->nullable();
        $table->string('name');
        $table->timestamps();// This line causes the issue.
        $table->softDeletes();
    });
}

//...

The error that is thrown when running it:

[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'created_at'
(SQL: create table `users` (
    `id` int unsigned not null auto_increment primary key, 
    `email` varchar(255) null, 
    `name` varchar(255) not null, 
    `created_at` timestamp default 0 not null, 
    `updated_at` timestamp default 0 not null, 
    `deleted_at` timestamp null
) default character set utf8 collate utf8_unicode_ci)

Laravel 5.1.8, running on the newest Homestead box (version 0.3.3).

Hmm, I'm having trouble recreating this on the latest Homestead. I can run
the default user migration fine and insert data.

On Sun, Nov 15, 2015 at 12:15 PM, Michaël Lecerf [email protected]
wrote:

The exception is thrown when creating the table itself, before inserting
any data.
This happens because the default value for timestamp fields is set to be 0.

Example of a crashing migration:

// ...public function up(){ Schema::create('users', function(Blueprint $table) { $table->increments('id'); $table->string('email')->unique()->nullable(); $table->string('name'); $table->timestamps();// This line causes the issue. $table->softDeletes(); });}//...

The error that is thrown when running it:

[IlluminateDatabaseQueryException]
SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'created_at'
(SQL: create table users (
id int unsigned not null auto_increment primary key,
email varchar(255) null,
name varchar(255) not null,
created_at timestamp default 0 not null,
updated_at timestamp default 0 not null,
deleted_at timestamp null
) default character set utf8 collate utf8_unicode_ci)

Laravel 5.1.8, running on the latest Homestead version (v0.3.3).

—
Reply to this email directly or view it on GitHub
https://github.com/laravel/framework/issues/3602#issuecomment-156841038.

Weird. I'm running into this same issue when trying to run migrations after updating Homestead to 0.3.3 with Laravel 5.0.16

SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'created_at'

For what it's worth, replacing $table->timestamps() with the following seems to be a workaround:

$table->timestamp('created_at')->default(\DB::raw('CURRENT_TIMESTAMP'));
$table->timestamp('updated_at')->default(\DB::raw('CURRENT_TIMESTAMP'));

I have the exact same issue since installing Homestead yesterday...

Looks like this has been a problem before, http://stackoverflow.com/a/30555920

Would love to see this fixed or made as a comment in the documentation that you should be wary for this and maybe change the setting mentioned in the stackoverflow answer for the Homestead boxes!?

Hmm, I'm having trouble recreating this on the latest Homestead. I can run the default user migration fine and insert data.

It also works for me on a blank Laravel install (5.1.24). The two default migrations run without any problem and create the tables in the homestead database. Weird.

Did you tweak anything in MySQL’s configuration on your own Homestead instance? As far as I get it, the issue seems related to this SQL mode (NO_ZERO_DATE). Which is deprecated in the latest MySQL versions (such as the one shipped with the latest Homestead box).

Ah, I have found the issue a fix, probably.

My "old" database.php config file does not have strict set to false ('strict' => false) as laravel/laravel does. When I add that line to the mysql config, all migrations work just fine (in my case)...

Edit: I noticed it doesn't matter what the value of strict is, as long as it's present it won't fail (checked on clean Laravel install).

@Stayallive

Wow. Doing _exactly the opposite_ seems to fix the issue on my side. This setting was already set to false (its default value) and switching it to true allows my migrations to run without any problem.

Now I don’t understand anything any more…

Wait wut... this is not the Laravel magic I heard about 😜

I have the same problem after upgrade. My solution:

  • use nullableTimestamps() instead of timestamps()
  • for custom timestamps add nullable , ex: timestamp('xxxx')->nullable()

It's deprecated but included as part of strict mode.

Laravel _should_ be strict compliant by default.
On Nov 16, 2015 12:31 PM, "Michaël Lecerf" [email protected] wrote:

Hmm, I'm having trouble recreating this on the latest Homestead. I can run
the default user migration fine and insert data.

It also works for me on a blank Laravel install (5.1.24). The two default
migrations run without any problem and create the tables in the homestead
database. Weird.

Did you tweak anything in MySQL’s configuration on your own Homestead
instance? As far as I get it, the issue seems related to this SQL mode
https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_no_zero_date
(NO_ZERO_DATE). Which is deprecated in the latest MySQL versions (such as
the one shipped with the latest Homestead box).

—
Reply to this email directly or view it on GitHub
https://github.com/laravel/framework/issues/3602#issuecomment-157160686.

Running into the same issue on an application built using Laravel 4.2.17 & laravel/homestead' (v0.3.3). I've tried adding the 'strict'=>false setting to the database config, but that doesn't seem to do the trick.

I just updated Laravel Homestead, that is using MySQL 5.7.9 now, and got the same issue.

It's fixed in the very latest 5.1.x dev version atm.

It'll be available in 5.1.25 once it's released.

I see it's going to use default timestamp as the default. Wouldn't it be better to just skip default value entirely?

That's what the fix is I think.

It's fixed in the very latest 5.1.x dev version atm.

Any plan/possibility to backport a fix to 4.x and/or 5.0?

You could set explicit_defaults_for_timestamp to TRUE in your MySQL server configuration file.

I have set explicit_defaults_for_timestamp = TRUE in the my.cnf file and restarted the mysqld server, but I still get the same error, but when I set the config/database.php strict to true, this issue #3602 gets resolved and another (unrelated issue?) crops up.

Currently on Laravel 5.0.33

edit: Went back and revised any changes I made, then set nullable() to every custom timestamp('xxxx') I had as well as changing some default seed parameters, and finally have it running

As @sorinstanila already mentioned, there's also nullableTimestamps() method as a workaround for now.

Strict set to false fixed this for me. Thanks for the help.

From @uberbrady in https://github.com/snipe/snipe-it/issues/1303

MySQL released a new version of their docker container which runs in a more strict mode. If you specifically pick out a MySQL version running 5.6 or earlier, it won't happen. I'm updating documentation to note that.

Strict set to false fixed this for me. Any updates on a permanent fix?

There is no "permanent" fix other than either turning off strict mode or putting a valid time stamp on the column when you insert it.

On Mon, Nov 23, 2015 at 1:08 PM, Trevor Greenleaf
[email protected] wrote:

Strict set to false fixed this for me. Any updates on a permanent fix?

Reply to this email directly or view it on GitHub:
https://github.com/laravel/framework/issues/3602#issuecomment-159030482

@taylorotwell Why don't you add a new method called currentTimestamps which has defaults as shown in my original query?

0 is not a good default because it doesn't work in strict mode/NO_ZERO_DATE and null doesn't work either if you want those columns to always be non-null.

I'd say you should update the base timestamps but multiple CURRENT_TIMESTAMPs doesn't work on older versions of MySQL, so for backwards compat I'd just make it a new method.

We already added a new helper ->useCurrent() but it may not be tagged yet.

On Mon, Nov 23, 2015 at 2:19 PM, Mark Penner [email protected]
wrote:

@taylorotwell Why don't you add a new method called currentTimestamps which has defaults as shown in my original query?
0 is not a good default because it doesn't work in strict mode/NO_ZERO_DATE and null doesn't work either if you want those columns to always be non-null.

I'd say you should update the base timestamps but multiple CURRENT_TIMESTAMPs doesn't work on older versions of MySQL, so for backwards compat I'd just make it a new method.

Reply to this email directly or view it on GitHub:
https://github.com/laravel/framework/issues/3602#issuecomment-159052364

Refs #10962 (then https://github.com/laravel/framework/commit/15c487fecc00c1a58837ce5692396fec78a5bd9d).

So, you have 3 sensible solutions:

  • Use ->nullable() in your database schema
  • Use ->useCurrent() if suitable (or even ->default(yourpick)…)
  • Specify a value when inserting row

Laravel 5.1 + MySQL 5.7 requires to specify either nullable or a default value in the schema.
Laravel 5.2 + MySQL 5.7 doesn't require it, as long as you specify a value when inserting row.

Good catch about the multiple CURRENT_TIMESTAMP restriction.
This has been lifted only starting from MySQL 5.6…

@vlakoff Keep in mind that if you do nothing about the schema and just rely on inserting proper values, you won't be able to alter the table in any way. Any change in the structure, like adding/renaming/removing any columns will throw the following error: Invalid default value for 'some_column'.

I've edited my comment above to clarify this.

May this help?

sudo vi /etc/mysql/my.cnf

add (in [mysqld] section)
​sql_mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"

restart

More info at http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html . The configuration above may depend on your mysql version.

@dbillionlabs You are suggesting a whole bunch of settings irrelevant to the topic. It's enough to just remove NO_ZERO_DATE mode. But still, this is kind of a workaround, having this mode on is very good idea allowing you to avoid invalid values.

@kokokurak Hello, as I didn't found a way to remove just two (NO_ZERO_IN_DATE, NO_ZERO_DATE) from my.cnf, what I've just copied are the default values for sql_mode in mysql 5.7 without these ones, as stated on the link

The default SQL mode in MySQL 5.7 includes these modes: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION.

@dbillionlabs thanks for your hint. So I tried this and that's as far as I get (inside a laravel/homestead vagrant environment):

mysql> set sql_mode="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION";
Query OK, 0 rows affected, 1 warning (0.00 sec)

After running _php artisan platform:install_ the same error still shows up:

Error
_[PDOException] SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for 'created_at'_

What I haven't done is restarting the mysql-Server. Is that needed, and if so, how?

Thanks guys for digging into the research!

@hithereimhere try

SET GLOBAL sql_mode = 'modes';

but if it works for you know be aware next time mysql restarts you may lose the change, unless yoy modify mysql config file/s

@dbillionlabs thanks for the feedback, it tried it by setting it global and afterwards quit the mysql mode by q

After that, the laravel-installer came up with the same error. So still no progress.

Some more ways came to my mind:
1) Is it possible to downgrade the mysql version (< 5.7) inside Laravel/Homestead? (Couldn't find anything on that)
2) Is it possible to re-install an older Version of Laravel/Homestad? (Couldn't find any infos about specific older versions running < mysql 5.7)
3) Is there an official announcement from the Laravel community with a general workaround/solution?

For me on all my apps the solution was to set strict to true in my MySQL config (in config/database.php).

    'connections' => [

        'mysql' => [

            'driver'    => 'mysql',
            'host'      => 'localhost',
            'database'  => env('DB_DATABASE', 'homestead'),
            'username'  => env('DB_USERNAME', 'homestead'),
            'password'  => env('DB_PASSWORD', 'secret'),
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
            'strict'    => true

        ]

    ],

@Stayallive Sir, it looks like you saved my weekend.

One thing: I'm working with Cartalyst/Platform. So here's exactly what worked for me:

1) Set 'strict' => true in config/database.php
2) Run web-installer: (myapp.app/installer)

Info: Running _php artisan platform:install_ from console didn't work for me. It somehow overwrites/ignores the strict settings from config/database.php, but maybe that was just in my case.

Thanks so much guys!

Yes, I also had this issue.
Solution was to set strict to true.

Worked fine now. Will have to remember that for each project as it only seems to affect our developers on homestead.

@Stayallive - Solution worked for my laravel 5.0 project

I just ran into this issue after setting up an existing 5.0 project on a new computer. After updating config/database.php, I was able to run migrations successfully using $ php artisan migrate:refresh --seed.

Thanks

Same issue here as well with 5.0. I had to recreate my homestead box and migration would fail on the new box. Choked on first migation which was the default user table. Setting the mysql driver to strict allowed me to run the migrations.

-> useCurrent() helper doesn't work on timestamps() ?

Having the same issue,

Here's my environment:

➜  project git:(master) ✗ php artisan --version
Laravel Framework version 5.1.26 (LTS)
➜  project git:(master) ✗ mysql --version
mysql  Ver 14.14 Distrib 5.7.10, for osx10.11 (x86_64) using  EditLine wrapper
➜  project git:(master) ✗ php -v
PHP 5.6.16 (cli) (built: Nov 28 2015 19:43:54) 
Copyright (c) 1997-2015 The PHP Group
Zend Engine v2.6.0, Copyright (c) 1998-2015 Zend Technologies

Sequel Pro (MySQL client on OSX) gives me the same error by the way on the same created_at column.

I had the same problem.

vagrant ssh
sudo vi /etc/mysql/my.cnf
add sql-mode="allow_invalid_dates"
save
sudo service nginx restart

works like a charm :)

*** Note
If it doesn't work after nginx restart do a vagrant reload --provision

As discussed in the MySQL docs for 5.7, MySQL 5.7.8+ enables NO_ZERO_DATE by default, but strict mode does not include NO_ZERO_DATE. Thus the workaround to enable strict mode really does work. _However_, it is only a temporary fix and will in the future cause the very same issues to return.

Thus the final, long-lasting solution will be to create your timestamp columns with $table->timestamp('created_at')->useCurrent(); followed by $table->timestamp('updated_at')->useCurrent(); instead of using $table->timestamps()

@GrahamCampbell @taylorotwell - sorry - this is still broken on 5.1.28 on the current versions of Homestead and Forge installations (with the default mySQL 5.6 config that both use)

You can do a migration "ok".

But if you then run a mysqldump (which is common for backups) - then try and import that same SQL file into that same server (or another) - it will fail. This is important - because I just had to do an emergency migration - and the migration failed due to this issue.

The problem is only with $table->timestamps() because they are still creating a field of:

  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',

So I had to manually "find and replace" the contents of the SQL file and change them to this:

  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

I tested running a new migration on 5.1.28, then dumping the file, and trying to import, and the issue remains. And I cant use ->useCurrent() because that does not work on $table->timestamps()

So the only option at the moment is to remove $table->timestamps() and manually write both fields for new migrations:

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

It sounds like you needed to turn off MySQL strict mode?

On Jan 24, 2016, 3:49 AM -0600, Laurence [email protected], wrote:

@GrahamCampbell(https://github.com/GrahamCampbell)@taylorotwell(https://github.com/taylorotwell)- sorry - this is still broken on 5.1.28 on the current versions of Homestead and Forge installations (with the default mySQL 5.6 config that both use)

You can do a migration "ok".

But if you then run a mysqldump (which is common for backups) - then try and import that same SQL file into that same server (or another) - it will fail. This is important - because I just had to do an emergency migration - and the migration failed due to this issue.

The problem is only with$table->timestamps()because they are still creating a field of:

created_at timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', updated_at timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',

So I had to manually "find and replace" the contents of the SQL file and change them to this:

created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,

I tested running a new migration on 5.1.28, then dumping the file, and trying to import, and the issue remains.

—
Reply to this email directly orview it on GitHub(https://github.com/laravel/framework/issues/3602#issuecomment-174273850).

Typically it requires enabling strict mode.
The issue is that an out of the box homestead install and an out of the box Laravel install with migrations based on the docs will not work.

@taylorotwell - yes, that would also solve it. But the point is the "default" Forge and "default" Homestead configs dont have that - so the "default" Laravel 5.1.28 runs into issues.

It would be nice if something changed so all the "defaults" align? Currently they dont...

@taylorotwell As mentioned in my previous post NO_ZERO_DATE is currently a feature in flux. TheShiftExchange is correct in his explanation of the workaround.

Credits to @dbillionlabs for his answer. It removed the maggots in my head.

@taylorotwell Could you make $table->timestamps() default to either nullable() or useCurrent() on 5.1, like you did in commit 720a116897a4cc6780fa22f34d30c5986eafc581 to 5.2?

He doesn't seem to care to understand this one.

$this->capsule->addConnection(
[
'driver' => 'mysql',
'host' => '127.0.0.1',
'database' => 'xxxx',
'username' => 'xxxx',
'password' => 'xxxx',
'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
'port' => '33060',
'prefix' => '',
'strict' => true
]);

Setting strict => true solved the problem for me.

@Stayallive thank you for saving my time. It works.

Thanks @andela-tolotin

For people like me who have just updated to mysql 5.7 and faced this issue and google search results landed them here...
use the below link
https://mattstauffer.co/blog/how-to-disable-mysql-strict-mode-on-laravel-forge-ubuntu

for the issue with strict mode true , check
https://laravel.com/docs/5.3/upgrade#upgrade-5.2.0

MySQL Dates

Starting with MySQL 5.7, 0000-00-00 00:00:00 is no longer considered a valid date, since strict mode is enabled by default. All timestamp columns should receive a valid default value when you insert records into your database. You may use the useCurrent method in your migrations to default the timestamp columns to the current timestamps, or you may make the timestamps nullable to allow null values:

$table->timestamp('foo')->nullable();

$table->timestamp('foo')->useCurrent();

$table->nullableTimestamps();

kinda dump that something like that wasnt properly documented

Migrating old tables works like that:

Schema::table(
            'table',
            function (Blueprint $table) {
                $table->dateTime('created_at')->nullable()->default(NULL)->change();
                $table->dateTime('updated_at')->nullable()->default(NULL)->change();
            }
        );

Setting strict => true fixed it for me as well on MySQL 5.7

Adding this here for simple workaround reference...
I just ran into this on laravel 5.7 with mysql 8.0.12 using schema dumps from a legacy project that we are rewriting parts of in laravel. We are using schema dumps for existing tables to ensure consistency with the existing schemas like this:
Schema::table('some_table_name', function (Blueprint $table) {
DB::statement("CREATE TABLE some_table_name ( /* insert create table info here */);
});
Example problem line: msg_sent_on datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
Workaround: in config/database.php change mysql strict to false like so:
'mysql' => [
'driver' => 'mysql',
// other stuff
'strict' => false, // this is the workaround
]
Now all the existing schemas (originally created on mysql 5.6) migrate fine in mysql 8.0.12

i got this same error
SQLSTATE[42000]: Syntax error or access violation: 1067 Invalid default value for

Here is my solution to it on laravel 5.7
instead of using $table->timestamp('product_publish_date')
i replaced it by $table->timestamp('product_publish_date')->nullable()

also i modified my AppServiceProvider by adding this : use IlluminateSupportFacadesSchema;
and also i added Schema::defaultStringLength(191); in public function boot()

I'm locking this issue because it either has gone off-topic, become a dumping ground for things which shouldn't be in an issue tracker or is just too old.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

digirew picture digirew  Â·  3Comments

JamborJan picture JamborJan  Â·  3Comments

lzp819739483 picture lzp819739483  Â·  3Comments

RomainSauvaire picture RomainSauvaire  Â·  3Comments

gabriellimo picture gabriellimo  Â·  3Comments