Certainly! This is a common issue that can happen even on MySQL 8+ (including 8.4.x) and recent Laravel versions. The root cause is almost always related to character set and collation, index length limits, or an overlooked configuration. Here are steps to fully resolve the problem:
1. Check the Default String Length
You already set:
Schema::defaultStringLength(191);
But Unicode collations can still exceed index sizes depending on the DB config.
2. Set a Compatible Charset and Collation
Make sure your application and database are using a charset/collation that allows reasonable index lengths (ideally utf8mb4 with utf8mb4_unicode_ci).
In your .env file:
DB_CONNECTION=mysql
DB_DATABASE=your_database
DB_USERNAME=your_user
DB_PASSWORD=your_password
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_unicode_ci
In your config/database.php:
'mysql' => [
// ...
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
// ...
],
3. Check the Storage Engine
Make sure you're not using anything except InnoDB. MyISAM still has a 1000-byte index key length limit per key. MySQL 8+ should use InnoDB by default, but double-check with:
SHOW TABLE STATUS WHERE Name = 'failed_jobs';
If not, set it in your migration:
$table->engine = 'InnoDB';
4. Recreate the Database with the Right Defaults (Optional but recommended)
If possible, recreate your development database entirely with the proper charset/collation so new tables inherit the right settings:
CREATE DATABASE your_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
5. Clear All Caches and Config, Then Retry
php artisan config:clear
php artisan cache:clear
php artisan migrate:fresh
Example Migration Fix
Here’s what your migration should look like:
public function up()
{
Schema::create('failed_jobs', function (Blueprint $table) {
$table->id();
$table->string('uuid')->unique();
$table->text('connection');
$table->text('queue');
$table->longText('payload');
$table->longText('exception');
$table->timestamp('failed_at')->useCurrent();
$table->index(['connection', 'queue', 'failed_at']);
$table->engine = 'InnoDB'; // Force InnoDB
});
}
Note: If your
connectionorqueuefields are set astext(notstring), MySQL won’t be able to index them, so define proper lengths:
$table->string('connection', 100);
$table->string('queue', 100);
Or if you need to keep them as text due to large values, remove the index or make them string(191).
Why is This Happening Even On MySQL 8?
- If your DB/table/column uses
utf8mb4(4 bytes/char) and you have 3 string columns each 191 chars, that's3*191*4 = 2292bytes, exceeding the MySQL limit for index length per index. - Even InnoDB (MySQL 8+) restricts index bytes per key for some settings.
Summary Checklist
- Set
utf8mb4andutf8mb4_unicode_ciin both.envanddatabase.php. - Make sure your migration uses correct string lengths (
string('field', 191)). - Use InnoDB, not MyISAM.
- Recreate DB if possible.
- Clear caches and rerun.
References
- MySQL documentation: InnoDB Limits
- Laravel Docs on Indexes & String Length
- Laracasts: Common MySQL index issue thread
If you follow these steps, the error will be resolved. If not, paste your full migration and config/database.php, and I can look further.