ratchetphp/Ratchet · error · UnexpectedValueException

Expected instance of…

Error message

Expected instance of \Ratchet\WebSocket\MessageComponentInterface or \Ratchet\MessageComponentInterface

What it means

WsServer's constructor requires the wrapped component to implement either Ratchet\WebSocket\MessageComponentInterface or Ratchet\MessageComponentInterface; anything else (only implementing the lower-level DataComponentInterface or bare ComponentInterface) triggers an UnexpectedValueException. The message callbacks differ per interface, so WsServer refuses components it cannot dispatch messages to.

Solutions

  1. Make your application class implement Ratchet\MessageComponentInterface (onOpen/onMessage/onClose/onError) — the common case.
  2. Alternatively implement Ratchet\WebSocket\MessageComponentInterface if you need frame-level message metadata (e.g. subprotocols via WsServerInterface).
  3. If you truly need raw data access, use DataComponentInterface with the appropriate lower-level server setup instead of WsServer.

Example fix

// before
class Chat implements \Ratchet\ComponentInterface { /* no onMessage contract */ }
$ws = new \Ratchet\WebSocket\WsServer(new Chat());
// after
class Chat implements \Ratchet\MessageComponentInterface {
    public function onOpen(\Ratchet\ConnectionInterface $c) {}
    public function onMessage(\Ratchet\ConnectionInterface $c, $msg) {}
    public function onClose(\Ratchet\ConnectionInterface $c) {}
    public function onError(\Ratchet\ConnectionInterface $c, \Exception $e) {}
}
$ws = new \Ratchet\WebSocket\WsServer(new Chat());
Defensive patterns

Strategy: type-guard

Validate before calling

if (!($app instanceof \Ratchet\MessageComponentInterface) && !($app instanceof \Ratchet\WebSocket\MessageComponentInterface)) {
    throw new \LogicException('Component passed to WsServer must implement a MessageComponentInterface');
}
$ws = new \Ratchet\WebSocket\WsServer($app);

Type guard

function isWsCompatible($c): bool {
    return $c instanceof \Ratchet\MessageComponentInterface || $c instanceof \Ratchet\WebSocket\MessageComponentInterface;
}

Try / catch

try {
    $ws = new \Ratchet\WebSocket\WsServer($app);
} catch (\UnexpectedValueException $e) {
    // adapt the component before retrying
    $ws = new \Ratchet\WebSocket\WsServer(new ComponentAdapter($app));
}

Prevention

When it happens

Trigger: new WsServer($component) where $component implements neither MessageComponentInterface variant — e.g. only IoServer/ DataComponentInterface methods, or a typo'd class missing the onMessage contract.

Common situations: Wrapping a raw ConnectionInterface-style component in WsServer; building a custom middleware chain where an inner component lacks the message interface; forgetting to implement onMessage/onClose/onError after refactoring.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

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

     * @var \Closure
     */
    private $msgCb;

    /**
     * @param \Ratchet\WebSocket\MessageComponentInterface|\Ratchet\MessageComponentInterface $component Your application to run with WebSockets
     * @note If you want to enable sub-protocols have your component implement WsServerInterface as well
     */
    public function __construct(ComponentInterface $component) {
        if ($component instanceof MessageComponentInterface) {
            $this->msgCb = function(ConnectionInterface $conn, MessageInterface $msg) {
                $this->delegate->onMessage($conn, $msg);
            };
        } elseif ($component instanceof DataComponentInterface) {
            $this->msgCb = function(ConnectionInterface $conn, MessageInterface $msg) {
                $this->delegate->onMessage($conn, $msg->getPayload());
            };
        } else {
            throw new \UnexpectedValueException('Expected instance of \Ratchet\WebSocket\MessageComponentInterface or \Ratchet\MessageComponentInterface');
        }

        if (bin2hex('✓') !== 'e29c93') {
            throw new \DomainException('Bad encoding, unicode character ✓ did not match expected value. Ensure charset UTF-8 and check ini val mbstring.func_autoload');
        }

        $this->delegate    = $component;
        $this->connections = new \SplObjectStorage;

        $this->closeFrameChecker   = new CloseFrameChecker;

        if (self::isRFC6455v03()) {
            $this->handshakeNegotiator = new ServerNegotiator(new RequestVerifier);
        } else {
            $this->handshakeNegotiator = new ServerNegotiator(new RequestVerifier, new HttpFactory);
        }

        $this->handshakeNegotiator->setStrictSubProtocolCheck(true);

View on GitHub (pinned to e621c6c40b)