Rails 5 - Intermittent Error - ActiveRecord::NotNullViolation (Mysql2::Error: Field 'created_at' doesn't have a default value

Viewed 1165

need a bit of help :)

We have an intermittent error, where it says we have a null violation for one of our fields: created_at

We have several test environments, locally on our development environments we do not get this issue, but on our EC2 servers(built with AWS Elastic Beanstalk) we get the issue intermittently. We have not defined a default version for this as we should not need to, as Rails automatically populates this field with t.timestamps. Also we have the same created_at field in other tables without any issue. We have recently upgraded from rails 4 to rails 5 and rails 4 everything was working.

We started to compare our environment set ups and have found the following:

  • Ruby version 2.6.3 in all environments
  • Gemfile.lock - all gems matching between environments
  • mysql locally is:

mysql Ver 15.1 Distrib 5.5.64-MariaDB, for Linux (x86_64) using readline 5.1

and EC2 mysql is:

mysql Ver 14.14 Distrib 5.5.62, for Linux (x86_64) using readline 5.1

Intermittent Error:

ActiveRecord::NotNullViolation (Mysql2::Error: Field 'created_at' doesn't have a default value: INSERT INTO versions (updated_at) VALUES ('2020-02-25 10:55:50')) We are thinking about upgrading mysql - but not convinced that this is the issue. And it's not easy to upgrade it in AWS Elastic Beanstalk Schema.db

  create_table "versions", force: :cascade do |t|
    t.integer  "p_id",                        limit: 4
    t.string   "name",                              limit: 255
    t.text     "description",                       limit: 16777215
    t.datetime "created_at",                        null: false
    t.datetime "updated_at",                        null: false

Migration File:

class CreateVersions < ActiveRecord::Migration
  def change
    create_table :versions do |t|
      t.integer :p_id
      t.string :name
      t.string :description
      t.timestamps
    end
  end
end

Any ideas on how we can debug/ fix this?

1 Answers

Most of all the issue is in the cached information about the table columns. The reasons could be different:

  • you run the migration on-fly without server re-start;
  • you create/update records in the new table just after creating that table.

You need to reset the cache with Version.reset_column_information after running the migration (in the worst case put it directly into migration after create_table). Here's a link to the method documentation.

Or you can just re-start the server after running the migrations. All the cached columns information will be invalidated.

UPDATE

Another option I'd try is to specify Rails compatibility version in migration class (I set 4.2 here because you upgrade Rails from 4 to 5):

class CreateVersions < ActiveRecord::Migration[4.2]
end

The reason is that default timestamps behaviour has changed in Rails 5.0 and you get different results when run migration with different Rails versions. See this pull request for details. Here's the deprecation message they added:

timestamp was called without specifying an option for null. In Rails 5.0, this behavior will change to null: false. You should manually specify null: true to prevent the behavior of your existing migrations from changing.

With that [4.2] addition it should run migration with Rails 4 compatibility and add null: true to your timestamp fields.

You can also add null: true option manually into the migration. But anyway it's highly recommended to add [4.2] to all your migrations before upgrading Rails version.

Related