xuan1118's avatar

SQLSTATE[08S01] Exception is Always Thrown When New Processes Are Created

Horizon Version
5.40.1

Laravel Version
11.46.1 | 12.10.1

PHP Version
8.4.14

Redis Driver
PhpRedis

Redis Version
phpRedis 6.3.0

Database Driver & Version
pdo_sqlsrv 5.12.0, ODBC Driver 18 for SQL Server 18.5.1.1

Description

'supervisor-1' => [
    'connection' => 'redis',
    'queue' => ['default'],
    'balance' => 'auto',
    'autoScalingStrategy' => 'time',
    'maxProcesses' => 10,
    'maxTime' => 0,
    'maxJobs' => 0,
    'memory' => 128,
    'balanceMaxShift' => 1,
    'balanceCooldown' => 3,
    'tries' => 1,
    'timeout' => 60,
    'nice' => 0,
],

When new processes are created, failed tasks are consistently triggered, throwing the following exception:
SQLSTATE[08S01]: [Microsoft][ODBC Driver 18 for SQL Server]TCP Provider: Error code 0x2714 (Connection: sqlsrv, SQL: WAITFOR DELAY '00:00:30'; SELECT 1 as result)

Steps To Reproduce

Add the following to web routes:

Route::get('/test-08S01', function () {
    \App\Jobs\Test08S01Exception1Job::dispatch();
    return "successfully";
});

The exception occurs when tasks are processed concurrently.

0 likes
2 replies
Eimmaarose's avatar

It looks like the issue isn’t with Horizon itself, but with how SQL Server connections behave when child processes are spawned.

SQLSTATE[08S01] generally means the SQL Server connection is being dropped or is no longer valid by the time the job runs. This commonly happens when:

A database connection is opened before the worker forks

The new child process tries to reuse the same connection

SQL Server rejects it, causing 08S01 TCP errors

Why it happens

When Horizon auto-scales, it spawns new worker processes. If a database connection was already opened in the parent process (e.g., during bootstrap), the child processes inherit an invalid handle. As soon as they run a query, SQL Server throws the TCP Provider 0x2714 error.

Fixes Force Laravel to refresh DB connections per job

In your job, before running queries:

DB::purge('sqlsrv'); DB::reconnect('sqlsrv');

Disable persistent connections

In config/database.php, for the sqlsrv connection:

'persistent' => false,

Make sure no connection is made before forking

Any code that runs during boot and touches the DB should be avoided or delayed.

Restart workers after config change php artisan horizon:terminate

Why it only happens when new processes start

Parent worker is alive and its DB connection is valid

New workers inherit a connection that SQL Server considers invalid

First query in those workers immediately fails

Once workers reconnect, they continue working normally.

xuan1118's avatar

public function handle() { $job = 'Job:' . $this->job->getJobId(); Log::info("{$job} start");

try {
    $sql = "WAITFOR DELAY '00:00:30'; SELECT 1 as result";

    DB::purge('sqlsrv');

    DB::reconnect('lswldb')->select($sql);

    Log::info("{$job} end");

} catch (\Exception $e) {
    Log::error("{$job} Exception", [
        'exception' => get_class($e),
        'message'   => $e->getMessage(),
        'code'      => $e->getCode()
    ]);

    throw $e;
}

}

Adjusted the handle() method, but the issue still persists. It throws: SQLSTATE[08S01]: [Microsoft][ODBC Driver 18 for SQL Server]TCP Provider: Error code 0x2714 (Connection: sqlsrv, SQL: WAITFOR DELAY '00:00:30'; SELECT 1 as result)

In sqlsrv, the parameter 'persistent' => false should be ineffective.

Please or to participate in this conversation.