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

  1. Pass null (or omit) as the fourth argument to let SessionProvider auto-detect the serializer from ini_get('session.serialize_handler').
  2. Make the passed object implement Ratchet\Session\Serialize\HandlerInterface (with the four methods: open, close, unserialize/serialize pair per interface).
  3. Check the argument order of the constructor: ($app, $handler, $options, $serializer) and fix any shifted arguments.
  4. 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

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


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)