Laravel Migration Indexes Length

Laravel Migrations Laravel Migration Indexes Length

Specified key was too long

You may get this error when you start the first migration with users table migration:

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

The problem is in these lines:

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

Laravel creates a column with a length of 255 characters but cannot create an index for that column with 255 characters.

The default string length for migrations

\vendor\laravel\framework\src\Illuminate\Database\Schema\Builder.php

/**
 * The default string length for migrations.
 *
 * @var int|null
 */
public static $defaultStringLength = 255;   

Laravel tables default charset

Laravel uses the utf8mb4 character set by default (config/database.php).

'charset' => 'utf8mb4',

You can specify a default character set for the table (MySQL).

$table->charset = 'utf8mb4';

Laravel uses the InnoDB engine set by default and you can also specify the table storage engine.

$table->engine = "InnoDB";

Encodings specifications and Index Length

Encoding utf8mb4 uses 4 bytes for each symbol.

Encoding Latin1 or utf8 uses 3 bytes for each symbol.

The index key prefix length limit is 767 bytes for InnoDB tables that use the REDUNDANT or COMPACT row format.

Index Length for utf8mb4 is 767 / 4 = 191,75 symbols.

Index Length for Latin1 or utf8 is 767 / 3 = 255,66 symbols.

Solutions

1. Schema::defaultStringLength

You may configure this by calling the Schema::defaultStringLength method within your AppServiceProvider:

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

2. Migration String Lenght

You can define the string length in migration

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

3. Database Config Option innodb_large_prefix

Also may enable the innodb_large_prefix option for your database.

Notice

$defaultStringLength

Don't change $defaultStringLength default value in \vendor\laravel\framework\src\Illuminate\Database\Schema\Builder.php. The value can be reset after a Laravel update.