laravel/framework · error · Exception

Dump execution exceeded maximum depth of 30.

Error message

Dump execution exceeded maximum depth of 30.

What it means

MySqlSchemaState::executeDumpProcess recursively retries the mysqldump/mysql shell command when specific known error phrases appear in the failure message ('column-statistics' / 'column_statistics' and 'set-gtid-purged'), each retry stripping the offending flag and incrementing $depth. The depth>30 check is a safety net that converts a runaway recursion into a clear Exception. In practice only two retry conditions exist, so reaching depth 30 indicates the retry path is matching repeatedly without resolving — a sign the underlying process error keeps re-appearing after each flag is stripped.

Solutions

  1. Inspect the actual ProcessFailedException message from the inner catch (enable verbose artisan output / check logs) to see which error string is recurring.
  2. Pin a mysqldump client version that matches the server (8.0 client against 8.0 server, or MariaDB against MariaDB) to avoid the column-statistics mismatch entirely.
  3. If you customize the dump command via the schema state or connection config, ensure it does not re-append --column-statistics=0 or --set-gtid-purged after the retry strips them.
  4. Set config('database.connections.mysql.dump.column_statistics', false) (Laravel's db config) or upgrade past the Laravel version whose default flags conflict with your client.

Example fix

// before (config/database.php — client keeps adding column-statistics)
'mysql' => [ /* defaults */ ],

// after (explicitly disable the offending option)
'mysql' => [
    'driver' => 'mysql',
    'dump' => [
        'use_column_statistics' => false,
    ],
    // ...
],
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the mysqldump client version and the configured dump options before dumping
$version = DB::connection()->getPdo()->getAttribute(PDO::ATTR_CLIENT_VERSION);
// prefer disabling the flag at config level rather than relying on the retry path

Try / catch

use Illuminate\Database\Schema\MySqlSchemaState;
use Symfony\Component\Process\Exception\ProcessFailedException;

try {
    Artisan::call('schema:dump');
} catch (\Throwable $e) {
    if (str_contains($e->getMessage(), 'maximum depth of 30')) {
        // log inner ProcessFailedException details and align client/server versions
        report($e);
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Calling Schema::dump() / the migrate:fresh --seed path that triggers MySqlSchemaState (e.g. php artisan schema:dump or migration loading), where mustRun() keeps failing with one of the retry-triggering error strings on every recursion, e.g. a custom dump command template that re-adds the flags or a shell environment that rewrites the command line.

Common situations: Mismatched mysqldump client vs server versions repeatedly emitting 'column-statistics' errors; a configured dump binary path or process factory that injects --column-statistics back in after the grammar strips it; corrupted/looping shell quoting that breaks flag removal.

Related errors


AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11). Data as JSON: /api/errors/cfc866800f4b11b1. Report an issue: GitHub.

Appendix: source

Thrown at src/Illuminate/Database/MySqlSchemaState.php:182

View on GitHub (pinned to e0f6eb3518)