Laravel Migration Error: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes

MysqlLaravelPdoLaravel 5Laravel 5.4

Mysql Problem Overview


Migration error on Laravel 5.4 with php artisan make:auth

> [Illuminate\Database\QueryException] SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter tabl e users add unique users_email_unique(email)) > > [PDOException] SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes

Mysql Solutions


Solution 1 - Mysql

According to the official Laravel 7.x documentation, you can solve this quite easily.

Update your /app/Providers/AppServiceProvider.php to contain:

use Illuminate\Support\Facades\Schema;

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191);
}

> Alternatively, you may enable the innodb_large_prefix option for your database. Refer to your database's documentation for instructions on how to properly enable this option.

Solution 2 - Mysql

I don't know why the above solution and the official solution which is adding

Schema::defaultStringLength(191);

in AppServiceProvider didn't work for me. What worked for was editing the database.php file in config folder. Just edit

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',

to

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',

and it should work, although you will be unable to store extended multibyte characters like emoji.

This is an ugly hack and don't do if you want to store string in non english language, emoji

I did it with Laravel 5.7. Hope it helps.

Don't forget to stop and launch again the server.

Solution 3 - Mysql

I'm just adding this answer here as it's the quickest solution for me. Just set the default database engine to 'InnoDB' on

/config/database.php

'mysql' => [
    ...,
    ...,
    'engine' => 'InnoDB',
 ]

then run php artisan config:cache to clear and refresh the configuration cache

EDIT: Answers found here might explain what's behind the scenes of this one

Solution 4 - Mysql

Laravel 7.X (also works in 8X): Simple Solution.

Option-1:

php artisan db:wipe 

Update these values(Below) of mysql array in /config/database.php

> 'charset' => 'utf8', > 'collation' => 'utf8_general_ci', > And then

php artisan migrate

It's Done! Migration Tables will be created successfully.


Option-2:

Use php artisan db:wipe or delete/drop all the tables of your database manually.

Update your AppServiceProvider.php [ Located in app/Providers/AppServiceProvider.php ]

use Illuminate\Support\Facades\Schema;
/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191); 
}

And then

php artisan migrate

It's Done!

Pitfall: I would like to mention of @shock_gone_wild 's comment

> Be careful about this solution (Option-2). If you index email fields for example, > stored emails can only have a max length of 191 chars. This is less > than the official RFC states.


Optionally I Tried out these possible ways (like below) but doesn't work.

php artisan config:cache php artisan migrate:fresh

php artisan migrate:reset

Solution 5 - Mysql

This issue is caused in Laravel 5.4 by the database version.

According to the docs (in the Index Lengths & MySQL / MariaDB section):

> Laravel uses the utf8mb4 character set by default, which includes > support for storing "emojis" in the database. If you are running a > version of MySQL older than the 5.7.7 release or MariaDB older than > the 10.2.2 release, you may need to manually configure the default > string length generated by migrations in order for MySQL to create > indexes for them. You may configure this by calling the > Schema::defaultStringLength method within your AppServiceProvider.

In other words, in <ROOT>/app/Providers/AppServiceProvider.php:

// Import Schema
use Illuminate\Support\Facades\Schema;
// ...

class AppServiceProvider extends ServiceProvider
{

public function boot()
{
    // Add the following line
    Schema::defaultStringLength(191);
}

// ...

}

But as the comment on the other answer says:

> Be careful about this solution. If you index email fields for example, > stored emails can only have a max length of 191 chars. This is less > than the official RFC states.

So the documentation also proposes another solution:

> Alternatively, you may enable the innodb_large_prefix option for your > database. Refer to your database's documentation for instructions on > how to properly enable this option.

Solution 6 - Mysql

For someone who don't want to change AppServiceProvider.php. (In my opinion, it's bad idea to change AppServiceProvider.php just for migration)

You can add back the data length to the migration file under database/migrations/ as below:

create_users_table.php

$table->string('name',64);
$table->string('email',128)->unique();

create_password_resets_table.php

$table->string('email',128)->index();

Solution 7 - Mysql

I have solved this issue and edited my config->database.php file to like my database ('charset'=>'utf8') and the ('collation'=>'utf8_general_ci'), so my problem is solved the code as follow:

'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8',
        'collation' => 'utf8_general_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
    ],

Solution 8 - Mysql

I am adding two sollution that work for me.

1st sollution is:

  1. Open database.php file insde config dir/folder.
  2. Edit 'engine' => null, to 'engine' => 'InnoDB',

This worked for me.

2nd sollution is:

  1. Open database.php file insde config dir/folder.
    2.Edit
    'charset' => 'utf8mb4', 'collation' => 'utf8mb4_unicode_ci',
    to

'charset' => 'utf8', 'collation' => 'utf8_unicode_ci',


Goodluck

Solution 9 - Mysql

1- Go to /config/database.php and find these lines

'mysql' => [
    ...,
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci',
    ...,
    'engine' => null,
 ]

and change them to:

'mysql' => [
    ...,
    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',
    ...,
    'engine' => 'InnoDB',
 ]

2- Run php artisan config:cache to reconfigure laravel

3- Delete the existing tables in your database and then run php artisan migrate again

Solution 10 - Mysql

I have found two solutions for this error

OPTION 1:

Open your user and password_reset table in database/migrations folder

And just change the length of the email:

$table->string('email',191)->unique();

OPTION 2:

Open your app/Providers/AppServiceProvider.php file and inside the boot() method set a default string length:

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}

Solution 11 - Mysql

The solution no one tells is that in Mysql v5.5 and later InnoDB is the default storage engine which does not have this problem but in many cases like mine there are some old mysql ini configuration files which are using old MYISAM storage engine like below.

default-storage-engine=MYISAM

which is creating all these problems and the solution is to change default-storage-engine to InnoDB in the Mysql's ini configuration file once and for all instead of doing temporary hacks.

default-storage-engine=InnoDB

And if you are on MySql v5.5 or later then InnoDB is the default engine so you do not need to set it explicitly like above, just remove the default-storage-engine=MYISAM if it exist from your ini file and you are good to go.

Solution 12 - Mysql

works like charm for me!

Add this to config/database.php

'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',

instead of

'engine' => 'null',

Solution 13 - Mysql

Instead of setting a limit on length I would propose the following, which has worked for me.

Inside:

> config/database.php

replace this line for mysql:

'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',

with:

'engine' => null,

Solution 14 - Mysql

As already specified we add to the AppServiceProvider.php in App/Providers

use Illuminate\Support\Facades\Schema;  // add this

/**
 * Bootstrap any application services.
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191); // also this line
}

you can see more details in the link bellow (search for "Index Lengths & MySQL / MariaDB") https://laravel.com/docs/5.5/migrations

BUT WELL THAT's not what I published all about! the thing is even when doing the above you will likely to get another error (that's when you run php artisan migrate command and because of the problem of the length, the operation will likely stuck in the middle. solution is below, and the user table is likely created without the rest or not totally correctly) we need to roll back. the default roll back will not work. because the operation of migration didn't like finish. you need to delete the new created tables in the database manually.

we can do it using tinker as in below:

L:\todos> php artisan tinker

Psy Shell v0.8.15 (PHP 7.1.10 — cli) by Justin Hileman

>>> Schema::drop('users')

=> null

I myself had a problem with users table.

after that you're good to go

php artisan migrate:rollback

php artisan migrate

Solution 15 - Mysql

As outlined in the Migrations guide to fix this, all you have to do is edit your app/Providers/AppServiceProvider.php file and inside the boot method set a default string length:

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}

Note: first you have to delete (if you have) users table, password_resets table from the database and delete users and password_resets entries from migrations table.

To run all of your outstanding migrations, execute the migrate Artisan command:

php artisan migrate

After that everything should work as normal.

Solution 16 - Mysql

If you want to change in AppServiceProvider then you need to define the length of email field in migration. just replace the first line of code to the second line.

create_users_table

$table->string('email')->unique();
$table->string('email', 50)->unique();

create_password_resets_table

$table->string('email')->index();
$table->string('email', 50)->index();

After successfully changes you can run the migration.
Note: first you have to delete (if you have) users table, password_resets table from the database and delete users and password_resets entries from migration table.

Solution 17 - Mysql

Schema::defaultStringLength(191); will define the length of all strings 191 by default which may ruin your database. You must not go this way.

Just define the length of any specific column in the database migration class. For example, I'm defining the "name", "username" and "email" in the CreateUsersTable class as below:

public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name', 191);
            $table->string('username', 30)->unique();
            $table->string('email', 191)->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

Solution 18 - Mysql

I have just modified following line in users and password_resets migration file.

Old : $table->string('email')->unique();

New : $table->string('email', 128)->unique();

Solution 19 - Mysql

The recommended solution is to enable innodb_large_prefix option of MySQL so you won't be getting into subsequent problems. And here is how to do that:

Open the my.ini MySQL configuration file and add the below lines under the [mysqld] line like this.

[mysqld]
innodb_file_format = Barracuda
innodb_large_prefix = 1
innodb_file_per_table = ON

After that, save your changes and restart your MySQL service.

Rollback if you need to and then re-run your migration.


Just in case your problem still persists, go to your database configuration file and set

'engine' => null, to 'engine' => 'innodb row_format=dynamic'

Hope it helps!

Solution 20 - Mysql

In order to avoid changing anything in your code, simply update your MySQL server to at least 5.7.7

Reference this for more info : https://laravel-news.com/laravel-5-4-key-too-long-error

Solution 21 - Mysql

This is common since Laravel 5.4 changed the default database charater set to utf8mb4. What you have to do, is: edit your App\Providers.php by putting this code before the class declaration

use Illuminate\Support\Facades\Schema;

Also, add this to the 'boot' function Schema::defaultStringLength(191);

Solution 22 - Mysql

If you don't have any data assigned already to you database do the following:

  1. Go to app/Providers/AppServiceProvide.php and add

> use Illuminate\Support\ServiceProvider;

and inside of the method boot();

> Schema::defaultStringLength(191);

  1. Now delete the records in your database, user table for ex.

  2. run the following

> php artisan config:cache > > php artisan migrate

Solution 23 - Mysql

I think to force StringLenght to 191 is a really bad idea. So I investigate to understand what is going on.

I noticed that this message error :

> SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key > was too long; max key length is 767 bytes

Started to show up after I updated my MySQL version. So I've checked the tables with PHPMyAdmin and I've noticed that all the new tables created were with the collation utf8mb4_unicode_ci instead of utf8_unicode_ci for the old ones.

In my doctrine config file, I noticed that charset was set to utf8mb4, but all my previous tables were created in utf8, so I guess this is some update magic that it start to work on utf8mb4.

Now the easy fix is to change the line charset in your ORM config file. Then to drop the tables using utf8mb4_unicode_ci if you are in dev mode or fixe the charset if you can't drop them.

For Symfony 4

> change charset: utf8mb4 to charset: utf8 in config/packages/doctrine.yaml

Now my doctrine migrations are working again just fine.

Solution 24 - Mysql

first delete all tables of the database in the localhost

Change Laravel default database (utf8mb4) properties in file config/database.php to:

'charset' => 'utf8', 'collation' => 'utf8_unicode_ci',

after then Changing my local database properties utf8_unicode_ci. php artisan migrate it is ok.

Solution 25 - Mysql

Try with default string length 125 (for MySQL 8.0).

defaultStringLength(125)

Solution 26 - Mysql

in database.php

-add this line:

'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',

enter image description here

Solution 27 - Mysql

For anyone else who might run into this, my issue was that I was making a column of type string and trying to make it ->unsigned() when I meant for it to be an integer.

Solution 28 - Mysql

The approached that work here was pass a second param with the key name (a short one):

$table->string('my_field_name')->unique(null,'key_name');

Solution 29 - Mysql

I was getting this error even though I already had (actually because I already had) Schema::defaultStringLength(191); in my AppServiceProvider.php file.

The reason is because I was trying to set a string value in one of my migrations to a value higher than 191:

Schema::create('order_items', function (Blueprint $table) {
    $table->primary(['order_id', 'product_id', 'attributes']);
    $table->unsignedBigInteger('order_id');
    $table->unsignedBigInteger('product_id');
    $table->string('attributes', 1000); // This line right here
    $table->timestamps();
});

Removing the 1000 or setting it to 191 solved my issue.

Solution 30 - Mysql

Changing my local database server type from "mariadb" to "mysql" fixed this for me without having to edit any Laravel files.

I followed this tutorial to change my db server type: https://odan.github.io/2017/08/13/xampp-replacing-mariadb-with-mysql.html

Solution 31 - Mysql

You can set a string length of the indexed field as follows:

  $table->string('email', 200)->unique();

Solution 32 - Mysql

For Lumen:

Add to .env file

DB_ENGINE=InnoDB

Solution 33 - Mysql

Just a few lines in the /etc/mysql/mariadb.conf.d/50-server.cnf or wherever your config is:

innodb-file-format=barracuda
innodb-file-per-table=ON
innodb-large-prefix=ON
innodb_default_row_format = 'DYNAMIC'

and sudo service mysql restart

https://stackoverflow.com/a/57465235/778234

See the docs: https://dev.mysql.com/doc/refman/5.6/en/innodb-row-format.html

Solution 34 - Mysql

Need to create database using following command.

CREATE DATABASE database_name CHARACTER SET utf8 COLLATE utf8_general_ci;

and then run following command to migrate database tables.

php artisan migrate

Solution 35 - Mysql

If you have this error running "php artisan migrate". You can alter the table you want to update by writing this :

    DB::statement('ALTER TABLE table_name ROW_FORMAT = DYNAMIC;');        

In your migration script. Example :

class MyMigration extends Migration {

/**
 * Run the migrations.
 */
public function up()
{
    DB::statement('ALTER TABLE table_name ROW_FORMAT = DYNAMIC;');        
    Schema::table('table_name', function ($table) {
        //....
    });
}

/**
 * Undo the migrations.
 */
public function down()
{
    //....
}
}

And then run php artisan migrate again

Solution 36 - Mysql

The cleanest solution is to go to your database and change:

default_storage_engine to InnoDB

You most likely have there MyISAM.

Solution 37 - Mysql

Open this file here: /app/Providers/AppServiceProvider.php

And Update this code as my image:

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}

enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionabSiddiqueView Question on Stackoverflow
Solution 1 - MysqlabSiddiqueView Answer on Stackoverflow
Solution 2 - MysqlKoushik DasView Answer on Stackoverflow
Solution 3 - MysqlDexter BengilView Answer on Stackoverflow
Solution 4 - Mysqlperfectionist1View Answer on Stackoverflow
Solution 5 - MysqlEsteban HerreraView Answer on Stackoverflow
Solution 6 - MysqlhelloroyView Answer on Stackoverflow
Solution 7 - MysqlAhmad ShakibView Answer on Stackoverflow
Solution 8 - MysqlArslan Ahmad khanView Answer on Stackoverflow
Solution 9 - Mysqlseyed mohammad asghariView Answer on Stackoverflow
Solution 10 - MysqlUdhav SarvaiyaView Answer on Stackoverflow
Solution 11 - MysqlAli A. DhillonView Answer on Stackoverflow
Solution 12 - MysqlAlaa ElAlfiView Answer on Stackoverflow
Solution 13 - MysqlMd. Noor-A-Alam SiddiqueView Answer on Stackoverflow
Solution 14 - MysqlMohamed AllalView Answer on Stackoverflow
Solution 15 - Mysqluser9162235View Answer on Stackoverflow
Solution 16 - MysqlChintan KotadiyaView Answer on Stackoverflow
Solution 17 - MysqlFatema Tuz ZuhoraView Answer on Stackoverflow
Solution 18 - MysqlMahesh GaikwadView Answer on Stackoverflow
Solution 19 - MysqlSammieView Answer on Stackoverflow
Solution 20 - MysqlFenn-CSView Answer on Stackoverflow
Solution 21 - MysqlTreasureView Answer on Stackoverflow
Solution 22 - MysqlLevinski PolishView Answer on Stackoverflow
Solution 23 - MysqlKaizoku GambareView Answer on Stackoverflow
Solution 24 - MysqlGoldman.VahdettinView Answer on Stackoverflow
Solution 25 - MysqlAjayView Answer on Stackoverflow
Solution 26 - MysqlMizael ClistionView Answer on Stackoverflow
Solution 27 - MysqlBrynn BatemanView Answer on Stackoverflow
Solution 28 - MysqlTiago GouvêaView Answer on Stackoverflow
Solution 29 - MysqlJaceyView Answer on Stackoverflow
Solution 30 - MysqlAdam WinsterView Answer on Stackoverflow
Solution 31 - MysqlSmithView Answer on Stackoverflow
Solution 32 - MysqlScotty GView Answer on Stackoverflow
Solution 33 - MysqlNoBugsView Answer on Stackoverflow
Solution 34 - Mysqluser3216114View Answer on Stackoverflow
Solution 35 - MysqlRobin DelaporteView Answer on Stackoverflow
Solution 36 - MysqlKryptobaronsView Answer on Stackoverflow
Solution 37 - MysqlAmranur RahmanView Answer on Stackoverflow