ratchetphp/Ratchet · error · InvalidArgumentException
Argument #4 ($serializer) expected…
Error message
Argument #4 ($serializer) expected null|Ratchet\Session\Serialize\HandlerInterface
What it means
SessionProvider's constructor accepts an optional fourth argument $serializer that must be either null or an instance of Ratchet\Session\Serialize\HandlerInterface. Because the library supports legacy PHP versions without nullable type hints, it performs a manual instanceof check instead of relying on the engine's type validation, and throws InvalidArgumentException itself when the value is neither null nor a HandlerInterface.
Solutions
- Pass null (or omit) as the fourth argument to let SessionProvider auto-detect the serializer from ini_get('session.serialize_handler').
- Make the passed object implement Ratchet\Session\Serialize\HandlerInterface (with the four methods: open, close, unserialize/serialize pair per interface).
- Check the argument order of the constructor: ($app, $handler, $options, $serializer) and fix any shifted arguments.
- Type-check the value before constructing: assert($serializer instanceof HandlerInterface || $serializer === null).
Example fix
// before $provider = new SessionProvider($app, $handler, [], new \stdClass); // after $provider = new SessionProvider($app, $handler, [], null); // auto-detect // or implement Ratchet\Session\Serialize\HandlerInterface in your custom class
Defensive patterns
Strategy: type-guard
Validate before calling
if ($serializer !== null && !$serializer instanceof \Ratchet\Session\Serialize\HandlerInterface) {
throw new \InvalidArgumentException('$serializer must be null or HandlerInterface');
}
$provider = new SessionProvider($app, $handler, $options, $serializer); Type guard
function isValidSerializer($s): bool {
return $s === null || $s instanceof \Ratchet\Session\Serialize\HandlerInterface;
} Try / catch
try {
$provider = new SessionProvider($app, $handler, $options, $serializer);
} catch (\InvalidArgumentException $e) {
// fall back to auto-detected serializer
$provider = new SessionProvider($app, $handler, $options);
} Prevention
- Pass null and let SessionProvider auto-detect unless you have a custom serializer.
- Add a PHPDoc type ?HandlerInterface on your factory methods so static analysis catches wrong types.
- Keep constructor argument order documented: ($app, $handler, $options, $serializer).
- Run static analysis (PHPStan/Psalm) to catch non-HandlerInterface arguments.
When it happens
Trigger: Calling new SessionProvider($app, $handler, $options) with a fourth argument that is not null and does not implement Ratchet\Session\Serialize\HandlerInterface — e.g. passing a plain object, a wrong serializer class, or a misordered argument (an array or string landing in position 4).
Common situations: Copy-pasted constructor calls with arguments in the wrong order; passing Symfony's own serializer or a custom session class that only implements \SessionHandlerInterface; upgrades where a custom serializer class was refactored away from HandlerInterface.
Related errors
- Handler must be instance of SessionHandlerInterface
- Handler must be instance of SessionHandlerInterface
- Handler must be instance of SessionHandlerInterface
- Argument #4 ($loop) expected…
- Unable to parse session serialize handler
AI-assisted analysis of ratchetphp/Ratchet@e621c6c40b (2026-09-16).
Data as JSON: /api/errors/e42f1bfa6f245d6b.
Report an issue: GitHub.
Appendix: source
Thrown at src/Ratchet/Session/SessionProvider.php:49
* @var \SessionHandlerInterface
*/
protected $_null;
/**
* @var \Ratchet\Session\Serialize\HandlerInterface
*/
protected $_serializer;
/**
* @param \Ratchet\Http\HttpServerInterface $app
* @param \SessionHandlerInterface $handler
* @param array $options
* @param ?\Ratchet\Session\Serialize\HandlerInterface $serializer
* @throws \RuntimeException
*/
public function __construct(HttpServerInterface $app, \SessionHandlerInterface $handler, array $options = array(), $serializer = null) {
if ($serializer !== null && !$serializer instanceof HandlerInterface) { // manual type check to support legacy PHP < 7.1
throw new \InvalidArgumentException('Argument #4 ($serializer) expected null|Ratchet\Session\Serialize\HandlerInterface');
}
$this->_app = $app;
$this->_handler = $handler;
$this->_null = new NullSessionHandler;
ini_set('session.auto_start', 0);
ini_set('session.cache_limiter', '');
ini_set('session.use_cookies', 0);
$this->setOptions($options);
if (null === $serializer) {
$serialClass = __NAMESPACE__ . "\\Serialize\\{$this->toClassCase(ini_get('session.serialize_handler'))}Handler"; // awesome/terrible hack, eh?
if (!class_exists($serialClass)) {
throw new \RuntimeException('Unable to parse session serialize handler');
}
$serializer = new $serialClass;View on GitHub (pinned to e621c6c40b)