symfony/http-foundation · error · RuntimeException

Unable to create a session ID.

Error message

Unable to create a session ID.

What it means

MigratingSessionHandler::create_sid() generates a session ID via session_create_id(), which returns '' (falsy) on failure; that is turned into RuntimeException('Unable to create a session ID.'). It means PHP could not generate a new session identifier in the current runtime context.

Solutions

  1. Initialize the session runtime (appropriate php.ini session settings, writable save_path, valid save_handler) before ID generation
  2. Verify sessions are enabled in the SAPI being used (CLI/web) and session functions are not restricted (disable_functions)
  3. Only call create_sid() as part of the normal session start/regenerate flow rather than manually
  4. Generate the ID yourself with a CSPRNG fallback in a wrapper: bin2hex(random_bytes(16))

Example fix

// before
$migratingHandler->create_sid(); // RuntimeException when session runtime not ready
// after
if (PHP_SESSION_NONE === session_status()) {
    ini_set('session.use_strict_mode', '1');
    session_start();
}
$id = $migratingHandler->create_sid();
Defensive patterns

Strategy: try-catch

Validate before calling

if (PHP_SESSION_DISABLED === session_status()) {
    throw new RuntimeException('Sessions disabled in this environment; cannot migrate session IDs.');
}

Type guard

function sessionIdCreationAvailable(): bool
{
    return PHP_SESSION_DISABLED !== session_status() && function_exists('session_create_id');
}

Try / catch

try {
    $id = $migratingHandler->create_sid();
} catch (\RuntimeException $e) {
    if ($e->getMessage() === 'Unable to create a session ID.') {
        $id = bin2hex(random_bytes(16)); // CSPRNG fallback
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: session_create_id() failing — called without an initialized session environment, sessions disabled (e.g. CLI without session config), or PHP misconfiguration of the session save handler when the migrating handler asks for a fresh ID during session regeneration/migration.

Common situations: Long-running daemons/CLI workers using session handlers without proper session runtime setup; misconfigured session.save_path/save_handler in php.ini; calling create_sid() manually outside the normal session start/regenerate lifecycle.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of symfony/http-foundation@5aea19cd67 (2026-09-13). Data as JSON: /api/errors/923d02ca9f446c70. Report an issue: GitHub.

Appendix: source

Thrown at Session/Storage/Handler/MigratingSessionHandler.php:43

    private \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface $currentHandler;
    private \SessionHandlerInterface&\SessionUpdateTimestampHandlerInterface $writeOnlyHandler;

    public function __construct(\SessionHandlerInterface $currentHandler, \SessionHandlerInterface $writeOnlyHandler)
    {
        if (!$currentHandler instanceof \SessionUpdateTimestampHandlerInterface) {
            $currentHandler = new StrictSessionHandler($currentHandler);
        }
        if (!$writeOnlyHandler instanceof \SessionUpdateTimestampHandlerInterface) {
            $writeOnlyHandler = new StrictSessionHandler($writeOnlyHandler);
        }

        $this->currentHandler = $currentHandler;
        $this->writeOnlyHandler = $writeOnlyHandler;
    }

    public function create_sid(): string
    {
        return session_create_id() ?: throw new \RuntimeException('Unable to create a session ID.');
    }

    public function close(): bool
    {
        $result = $this->currentHandler->close();
        $this->writeOnlyHandler->close();

        return $result;
    }

    public function destroy(#[\SensitiveParameter] string $sessionId): bool
    {
        $result = $this->currentHandler->destroy($sessionId);
        $this->writeOnlyHandler->destroy($sessionId);

        return $result;
    }

View on GitHub (pinned to 5aea19cd67)