laravel/framework · error · RuntimeException

Due to PHP limitations, the fork driver may not be used with

Error message

Due to PHP limitations, the fork driver may not be used within web requests.

What it means

Thrown by ConcurrencyManager::createForkDriver() when the fork driver is requested outside of a CLI context. PHP's pcntl_fork is not available (and not safe) within a web request lifecycle, so the fork driver is gated behind runningInConsole(). RuntimeException is thrown.

Source

Thrown at src/Illuminate/Concurrency/ConcurrencyManager.php:48

     *
     * @return \Illuminate\Concurrency\ProcessDriver
     */
    public function createProcessDriver()
    {
        return new ProcessDriver($this->app->make(ProcessFactory::class));
    }

    /**
     * Create an instance of the fork concurrency driver.
     *
     * @return \Illuminate\Concurrency\ForkDriver
     *
     * @throws \RuntimeException
     */
    public function createForkDriver()
    {
        if (! $this->app->runningInConsole()) {
            throw new RuntimeException('Due to PHP limitations, the fork driver may not be used within web requests.');
        }

        if (! class_exists(Fork::class)) {
            throw new RuntimeException('Please install the "spatie/fork" Composer package in order to utilize the "fork" driver.');
        }

        return new ForkDriver;
    }

    /**
     * Create an instance of the sync concurrency driver.
     *
     * @return \Illuminate\Concurrency\SyncDriver
     */
    public function createSyncDriver()
    {
        return new SyncDriver;
    }

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Use the fork driver only in CLI/artisan contexts; switch the default to 'process' for web.
  2. Conditionally choose the driver based on app()->runningInConsole().
  3. Run the concurrent work as an artisan command or queued job dispatched from the request.

Example fix

// before
config(['concurrency.default' => 'fork']);

// after
config(['concurrency.default' => app()->runningInConsole() ? 'fork' : 'process']);
Defensive patterns

Strategy: fallback

Validate before calling

$driver = app()->runningInConsole() ? 'fork' : 'process';
config(['concurrency.default' => $driver]);

Type guard

function canUseFork(): bool { return app()->runningInConsole(); }

Try / catch

try {
    $driver = app(\Illuminate\Concurrency\ConcurrencyManager::class)->driver('fork');
} catch (\RuntimeException $e) {
    $driver = app(\Illuminate\Concurrency\ConcurrencyManager::class)->driver('process');
}

Prevention

When it happens

Trigger: Configuring config('concurrency.default', 'fork') and then dispatching concurrency work during an HTTP request, queue job run via web worker, or any non-CLI entry point.

Common situations: Defaulting the concurrency driver to 'fork' globally while the same code path runs in both artisan commands and HTTP controllers. Forgetting that queued jobs may run under the web SAPI in some setups.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/7a2d2190d4df5529.json. Report an issue: GitHub.