{"record":{"id":"02dbcfc9fc36df03","repo":"walkor/workerman","slug":"session-create-id-failed","errorCode":null,"errorMessage":"session_create_id() failed","messagePattern":"session_create_id\\(\\) failed","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Protocols/Http/Request.php","lineNumber":724,"sourceCode":"            return 0;\n        }\n        $filesEncodeStr .= urlencode($uploadKey) . '=' . count($files) . '&';\n        $files[] = $file;\n\n        return $sectionEndOffset + strlen($boundary) + 2;\n    }\n\n    /**\n     * Create session id.\n     *\n     * @return string\n     * @throws RuntimeException\n     */\n    public static function createSessionId(): string\n    {\n        $sid = session_create_id();\n        if ($sid === false) {\n            throw new RuntimeException('session_create_id() failed');\n        }\n        return $sid;\n    }\n\n    /**\n     * @param string $sessionName\n     * @param string $sid\n     * @param array $cookieParams\n     * @return void\n     */\n    protected function setSidCookie(string $sessionName, string $sid, array $cookieParams): void\n    {\n        if (!$this->connection) {\n            throw new RuntimeException('Request->setSidCookie() fail, header already send');\n        }\n        $this->connection->headers['Set-Cookie'] = [$sessionName . '=' . $sid\n            . (empty($cookieParams['domain']) ? '' : '; Domain=' . $cookieParams['domain'])\n            . (empty($cookieParams['lifetime']) ? '' : '; Max-Age=' . $cookieParams['lifetime'])","sourceCodeStart":706,"sourceCodeEnd":742,"githubUrl":"https://github.com/walkor/workerman/blob/1391112a61d23020e11e7b89f17050f6cfaea431/src/Protocols/Http/Request.php#L706-L742","documentation":"Request::createSessionId() wraps PHP's native session_create_id(). That function returns false (instead of throwing) when it cannot generate an id, which in practice happens when a native PHP session is already active in the process. Workerman then surfaces this as a RuntimeException.","triggerScenarios":"Legacy code called session_start() inside a worker process (FPM-style code reused in Workerman), or a bundled library opens the native session before a new session id must be created for a client without a session cookie.","commonSituations":"Porting an FPM application to Workerman; a composer package that calls session_start()/session_id() lazily; phpunit/bootstrap that started a session in the same process during tests.","solutions":["Search the codebase and vendor for session_start()/session_id() calls and remove them from code that runs inside Workerman workers","Use only Workerman's own session API ($request->session(), Session classes), never the native session functions","As a diagnostic, log session_status() in onWorkerStart to confirm PHP_SESSION_NONE"],"exampleFix":"// before (legacy FPM code inside a worker)\nsession_start();\n$session = $request->session(); // later -> session_create_id() failed\n\n// after\n$session = $request->session(); // Workerman manages the id itself","handlingStrategy":"validation","validationCode":"if (session_status() === PHP_SESSION_ACTIVE) {\n    // legacy code started a native session inside the worker - find and remove it\n    throw new LogicException('native session must not be started inside Workerman');\n}","typeGuard":null,"tryCatchPattern":"try { $sid = Request::createSessionId(); } catch (RuntimeException $e) { /* fallback id generation */ $sid = bin2hex(random_bytes(16)); }","preventionTips":["Grep app and vendor for session_start()/session_id() before porting FPM code into Workerman","Use only Workerman's Session API inside workers"],"tags":["php","workerman","session","session-id"],"backgroundTag":"session-already-active","analyzedSha":"1391112a61d23020e11e7b89f17050f6cfaea431","analyzedAt":"2026-08-21T02:05:46.744Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}