ratchetphp/Ratchet · error · UnexpectedValueException

$request can not be null

Error message

$request can not be null

What it means

WsServer::onOpen performs the WebSocket handshake and stores the HTTP upgrade request on the connection, so it requires the PSR-7 RequestInterface argument. When onOpen is invoked with a null request — meaning no HTTP request reached this component — an UnexpectedValueException is thrown because the handshake cannot proceed.

Solutions

  1. Ensure HttpServer (which parses the HTTP request) wraps WsServer: new IoServer(new HttpServer(new WsServer($app)), ...) so onOpen receives the RequestInterface.
  2. When calling onOpen yourself (tests/custom pipelines), pass a PSR-7 RequestInterface instance, e.g. new \GuzzleHttp\Psr7\ServerRequest('GET', '/').
  3. If using a router (Router/OriginCheck) keep it around WsServer so the request is forwarded, not consumed.

Example fix

// before
new \Ratchet\Server\IoServer(new \Ratchet\WebSocket\WsServer($chat), $sock); // WsServer gets null request
// after
new \Ratchet\Server\IoServer(
    new \Ratchet\Http\HttpServer(
        new \Ratchet\WebSocket\WsServer($chat)
    ),
    $sock
);
Defensive patterns

Strategy: type-guard

Validate before calling

if (null === $request) {
    // refuse to call WsServer::onOpen without an HTTP request
    throw new \LogicException('Wrap WsServer in HttpServer so onOpen receives a RequestInterface');
}
$wsServer->onOpen($conn, $request);

Type guard

function hasHandshakeRequest(?\Psr\Http\Message\RequestInterface $r): bool { return $r !== null; }

Try / catch

try {
    $wsServer->onOpen($conn, $request);
} catch (\UnexpectedValueException $e) {
    $conn->close(); // cannot handshake without the request
}

Prevention

When it happens

Trigger: Calling WsServer::onOpen($conn) directly without a RequestInterface (it is optional only for interface compatibility); wiring WsServer at the top of the component stack so it receives connections before an HTTP-processing middleware (e.g. HttpServer/router) populated the request; connections that bypassed the HTTP upgrade path.

Common situations: Stacking components in the wrong order in IoServer (WsServer must sit below/after HttpServer so it gets the parsed request); testing onOpen manually in unit tests; using a frontend proxy setup where the request object is stripped.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of ratchetphp/Ratchet@e621c6c40b (2026-09-16). Data as JSON: /api/errors/df6a37647e931841. Report an issue: GitHub.

Appendix: source

Thrown at src/Ratchet/WebSocket/WsServer.php:122

        $reusableUnderflowException = new \UnderflowException;
        $this->ueFlowFactory = function() use ($reusableUnderflowException) {
            return $reusableUnderflowException;
        };
    }

    private static function isRFC6455v03() {
        $reflection = new \ReflectionClass('Ratchet\RFC6455\Handshake\ServerNegotiator');
        return $reflection->getMethod('__construct')->getNumberOfRequiredParameters() === 1;
    }

    /**
     * {@inheritdoc}
     */
    #[HackSupportForPHP8] public function onOpen(ConnectionInterface $conn, ?RequestInterface $request = null) { /*
    public function onOpen(ConnectionInterface $conn, RequestInterface $request = null) { /**/
        if (null === $request) {
            throw new \UnexpectedValueException('$request can not be null');
        }

        $conn->httpRequest = $request;

        $conn->WebSocket            = new \StdClass;
        $conn->WebSocket->closing   = false;

        $response = $this->handshakeNegotiator->handshake($request)->withHeader('X-Powered-By', \Ratchet\VERSION);

        $conn->send(Message::toString($response));

        if (101 !== $response->getStatusCode()) {
            return $conn->close();
        }

        $wsConn = new WsConnection($conn);

        $streamer = new MessageBuffer(

View on GitHub (pinned to e621c6c40b)