{"record":{"id":"b5142faf2d9c71a3","repo":"phpmyadmin/phpmyadmin","slug":"session-not-found","errorCode":null,"errorMessage":"Session not found.","messagePattern":"Session not found\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/FlashMessenger.php","lineNumber":31,"sourceCode":"final class FlashMessenger\n{\n    private const STORAGE_KEY = 'FlashMessenger';\n\n    /** @var mixed[] */\n    private array|null $storage = null;\n\n    /** @psalm-var FlashMessageList */\n    private array $previousMessages = [];\n\n    /** @psalm-assert !null $this->storage */\n    private function initSessionStorage(): void\n    {\n        if ($this->storage !== null) {\n            return;\n        }\n\n        if (! isset($_SESSION)) {\n            throw new RuntimeException(__('Session not found.'));\n        }\n\n        $this->storage = &$_SESSION;\n\n        if (isset($this->storage[self::STORAGE_KEY])) {\n            $this->previousMessages = $this->storage[self::STORAGE_KEY];\n        }\n\n        $this->storage[self::STORAGE_KEY] = [];\n    }\n\n    public function addMessage(string $context, string $message, string $statement = ''): void\n    {\n        $this->initSessionStorage();\n\n        $this->storage[self::STORAGE_KEY][] = ['context' => $context, 'message' => $message, 'statement' => $statement];\n    }\n","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/phpmyadmin/phpmyadmin/blob/70d713dc39f5f7e0683c0ee38ab816b7e72b6a49/src/FlashMessenger.php#L13-L49","documentation":"FlashMessenger stores its messages in the PHP superglobal $_SESSION. initSessionStorage() bails out early if a storage reference already exists, and throws RuntimeException('Session not found.') when $_SESSION is not set — meaning session_start() was never called or the session was closed. This guards against silently losing flash messages.","triggerScenarios":"Calling addMessage, getMessages, or getCurrentMessages (or any code that does) before session_start() has run, after session_write_close()/session_abort(), or in a CLI/test context where no session was started.","commonSituations":"Session autostart disabled (session.auto_start=0) and no session_start() in bootstrap; flash message used after the response is sent and the session closed; long-running scripts that closed the session to unlock it; unit tests invoking FlashMessenger without a session fixture.","solutions":["Call session_start() before any FlashMessenger usage (ideally early in the bootstrap).","Ensure no code calls session_write_close()/session_abort() before flash messages are read or written; move those calls after message handling.","Enable session.use_strict_mode-compatible startup or set session.auto_start only if appropriate; otherwise explicitly start the session in tests/CLI before touching FlashMessenger.","Check that the session save handler works and that $_SESSION is actually populated (var_dump(isset($_SESSION)))."],"exampleFix":"// before\n$messenger = new FlashMessenger();\n$messenger->addMessage('Saved'); // RuntimeException: Session not found.\n\n// after\nif (session_status() !== PHP_SESSION_ACTIVE) {\n    session_start();\n}\n$messenger = new FlashMessenger();\n$messenger->addMessage('Saved');","handlingStrategy":"validation","validationCode":"if (session_status() !== PHP_SESSION_ACTIVE) {\n    session_start(); // must run before any FlashMessenger usage\n}\nif (!isset($_SESSION)) {\n    throw new RuntimeException('Session unavailable; cannot use flash messages.');\n}","typeGuard":"function sessionIsActive(): bool\n{\n    return session_status() === PHP_SESSION_ACTIVE && isset($_SESSION);\n}","tryCatchPattern":"try {\n    $messenger->addMessage('Saved');\n} catch (RuntimeException $e) {\n    if (str_contains($e->getMessage(), 'Session not found')) {\n        session_start();\n        $messenger->addMessage('Saved'); // retry once after starting the session\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Always start the session in the application bootstrap before any response logic.","Avoid session_write_close()/session_abort() until all flash messages have been consumed.","In CLI/tests, seed $_SESSION or start a session explicitly before using FlashMessenger.","Check session_status() early and log if the session is unexpectedly closed."],"tags":["session","php","state","flash-messages"],"backgroundTag":"invalid-state-transition","analyzedSha":"70d713dc39f5f7e0683c0ee38ab816b7e72b6a49","analyzedAt":"2026-09-13T19:13:03.620Z","contentChangedAt":"2026-09-13T19:13:03.620Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}