Common causes
- MySQL 5.6 / MariaDB 10.1 or older, where the InnoDB index limit is 767 bytes
- Tables using COMPACT or REDUNDANT row format instead of DYNAMIC
- MyISAM tables, which cap keys at 1000 bytes
- Laravel's default string length of 255 combined with utf8mb4
- Composite indexes whose combined columns exceed 3072 bytes even on MySQL 8
How to fix it
- Check your server version. Run SELECT VERSION();. MySQL 5.7.7+ and MariaDB 10.2.2+ use DYNAMIC row format and a 3072-byte limit by default, so the 767 error mostly means an older server or an old table.
- Laravel: limit default string length. In AppServiceProvider::boot() call Schema::defaultStringLength(191); so VARCHAR columns are 191 characters (764 bytes), then re-run migrations.
- Shorten the indexed column. Change VARCHAR(255) to VARCHAR(191) on indexed utf8mb4 columns if values never exceed 191 characters (emails, slugs usually don't).
- Use a prefix index. Index only the first characters, e.g. INDEX(url(191)). Note a prefix index cannot enforce full-column UNIQUE constraints.
- Switch to DYNAMIC row format and InnoDB. Run ALTER TABLE t ENGINE=InnoDB ROW_FORMAT=DYNAMIC; on old tables so they get the 3072-byte limit (requires innodb_file_per_table and Barracuda on MySQL 5.6).
- Upgrade the database server. Where possible move to MySQL 8.0+ or MariaDB 10.6+, which removes this limit for normal VARCHAR(255) utf8mb4 indexes.
Laravel app/Providers/AppServiceProvider.php
use Illuminate\Support\Facades\Schema;
public function boot(): void
{
Schema::defaultStringLength(191);
} How to stop it happening again
- Run a current MySQL 8 or MariaDB 10.6+ server
- Size indexed VARCHAR columns to the real maximum length of the data
- Use InnoDB with DYNAMIC row format for all tables