{"record":{"id":"1314e6202e584e4d","repo":"ratchetphp/Ratchet","slug":"handler-must-be-instance-of-sessionhandlerinterface","errorCode":null,"errorMessage":"Handler must be instance of SessionHandlerInterface","messagePattern":"Handler must be instance of SessionHandlerInterface","errorType":"validation","errorClass":"InvalidArgumentException","httpStatus":null,"severity":"error","filePath":"src/Ratchet/Session/Storage/VirtualSessionStorage.php","lineNumber":89,"sourceCode":"    public function save() {\n        // get the data from the bags?\n        // serialize the data\n        // save the data using the saveHandler\n//        $this->saveHandler->write($this->saveHandler->getId(),\n\n        if (!$this->saveHandler->isWrapper() && !$this->getSaveHandler()->isSessionHandlerInterface()) {\n            $this->saveHandler->setActive(false);\n        }\n\n        $this->closed = true;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function setSaveHandler($saveHandler = null) {\n        if (!($saveHandler instanceof \\SessionHandlerInterface)) {\n            throw new \\InvalidArgumentException('Handler must be instance of SessionHandlerInterface');\n        }\n\n        if (!($saveHandler instanceof VirtualProxy)) {\n            $saveHandler = new VirtualProxy($saveHandler);\n        }\n\n        $this->saveHandler = $saveHandler;\n    }\n}\n\n}\n","sourceCodeStart":71,"sourceCodeEnd":101,"githubUrl":"https://github.com/ratchetphp/Ratchet/blob/e621c6c40bf684bbbb877102416ad5303d05a9cc/src/Ratchet/Session/Storage/VirtualSessionStorage.php#L71-L101","documentation":"VirtualSessionStorage::setSaveHandler validates that the session save handler passed in implements \\SessionHandlerInterface and throws InvalidArgumentException when it does not. The constructor calls setSaveHandler, so this error fires as soon as a VirtualSessionStorage is built (or the method is called directly) with a handler that does not implement the interface. Ratchet requires the interface so it can transparently wrap any handler in VirtualProxy for its virtual (non-PHP-native) sessions.","triggerScenarios":"Passing null (the default) or an object not implementing \\SessionHandlerInterface to VirtualSessionStorage::__construct / setSaveHandler; e.g. a legacy custom session handler class missing the interface, or passing a fully-qualified class name string instead of an instance.","commonSituations":"Upgrading PHP where old session handler classes were written before SessionHandlerInterface existed; wiring a non-standard handler object; forgetting to instantiate the handler class (passing a string) inside a Symfony session factory integration.","solutions":["Pass an object implementing \\SessionHandlerInterface (e.g. new \\SessionHandler(), or Ratchet's SessionServiceProvider) to VirtualSessionStorage.","If you have a legacy handler, make it implement \\SessionHandlerInterface (add open/close/read/write/destroy/gc methods with interface-compatible signatures).","Wrap or adapt third-party handlers in your own class that implements \\SessionHandlerInterface before passing it in."],"exampleFix":"// before\n$storage = new \\Ratchet\\Session\\Storage\\VirtualSessionStorage('MYSESSION');\n$storage->setSaveHandler(new LegacyArrayHandler());\n// after\n$storage = new \\Ratchet\\Session\\Storage\\VirtualSessionStorage('MYSESSION');\n$storage->setSaveHandler(new \\SessionHandler()); // or any \\SessionHandlerInterface implementation","handlingStrategy":"type-guard","validationCode":"if (!$handler instanceof \\SessionHandlerInterface) {\n    throw new \\InvalidArgumentException('setSaveHandler requires a \\SessionHandlerInterface instance');\n}\n$storage->setSaveHandler($handler);","typeGuard":"function isValidSessionHandler($h): bool { return $h instanceof \\SessionHandlerInterface; }","tryCatchPattern":"try {\n    $storage = new \\Ratchet\\Session\\Storage\\VirtualSessionStorage('sid', $handler);\n} catch (\\InvalidArgumentException $e) {\n    // fall back to a default handler\n    $storage = new \\Ratchet\\Session\\Storage\\VirtualSessionStorage('sid', new \\SessionHandler());\n}","preventionTips":["Always instantiate the handler class before passing it — never pass a class-name string or null.","Assert instanceof \\SessionHandlerInterface in your DI/factory configuration.","Keep custom session handlers updated to implement \\SessionHandlerInterface after PHP upgrades."],"tags":["php","session","invalid-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"e621c6c40bf684bbbb877102416ad5303d05a9cc","analyzedAt":"2026-09-16T00:13:27.878Z","contentChangedAt":"2026-09-16T00:13:27.878Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}