laravel errno 150 foreign key constraint is incorrectly formed

In case of foreign keys, the referenced and referencing fields must have exactly the same data type.

You create the id fields in both users and firms as signed integers. However, you create both foreign keys as unsigned integers, therefore the creation of the keys fail.

You need to either add the unsigned clause to the id field definitions, or remove the unsigned clause from the foreign key fields.


This answer is not better than the six answers before it but it is a more comprehensive answer on what causes laravel-errno-150-foreign-key-constraint-is-incorrectly-formed and how to fix specifically for laravel.

1) Spelling : often at times a wrong spelling of the referenced column name or referenced table name can throw up this error and you won't know as the error trace is not very descriptive.

2) Unique : the referenced column must be unique or indexed either by adding ->primary() or adding ->unique() or adding ->index() to the column definition in your migration.

3) Data type : the referenced and referencing fields must have exactly the same data type. this can not be stressed enough.

  • for bigincrements expected data type is bigInteger('column_name')->unsigned();

  • for increments expected is integer('column_name')->unsigned(); etc.

4) Remnants : when this error occurs it does not mean that the table is not migrated rather it is migrated but the foreign key columns are not set and it is not added to the migration table hence running php artisan migrate:reset will remove other tables except the faulty tables, so a manual drop of the faulty table is recommended to avoid further errors.

5) Order : this is often the most usual cause of this error the table being referenced must be created or migrated before the reference table else artisan wont find where to integrate the foreign key. to ensure an order for the migration process rename the migration file example:

  • Table A:2014_10_12_000000_create_users_table.php and
  • Table B:2014_10_12_100000_create_password_resets_table.php

This indicates that Table A will always come before Table B to change that, i will rename Table B to 2014_10_11_100000_create_password_resets_table.php now it will migrate before Table A.

6) Enable Foreign Key : if all else fails then add Schema::enableForeignKeyConstraints(); inside your function up() before your migration code example:

class CreateUsersTable extends Migration
{
 /**
  * Run the migrations.
  *
  * @return void
  */
 public function up()
 {
    Schema::enableForeignKeyConstraints();
    Schema::create('users', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->string('email')->unique();
        $table->string('password');
        $table->rememberToken();
        $table->timestamps();
    });
 }

 /**
  * Reverse the migrations.
  *
  * @return void
  */
 public function down()
 {
    Schema::dropIfExists('users');
 }
}

To read more see laravel foreign key and laravel migrations

Mention any more fixes that i missed in the comments thanks.


For PHP laravel 5.8 use unsigned modifier in this format

$table->unsignedBigInteger('user_id');

drop all tables in the database and run the migration again


Most of the time this kind of error occurs due to the datatype mismatch on both the table.

Both primary key table & foreign key table should use same datatype and same option.

For example:

users

        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });

orders

 Schema::create('orders', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->bigInteger('product_id')->unsigned();
            $table->foreign('product_id')->references('id')->on('products');
            $table->bigInteger('user_id')->unsigned();
           $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');

            $table->timestamp('added_on');
        });

On above example, I am trying to assign foreign key to users table from order table but I have bigInteger datatable in order table while in user table, I have simple integer. That's why it's generated this kind of error.

Also, If you have used unsigned(), nullable() etc options with primary or foreign key then you should use same at both the place.