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
- Make your application class implement Ratchet\MessageComponentInterface (onOpen/onMessage/onClose/onError) — the common case.
- Alternatively implement Ratchet\WebSocket\MessageComponentInterface if you need frame-level message metadata (e.g. subprotocols via WsServerInterface).
- 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
- Have app classes implement Ratchet\MessageComponentInterface as the default choice.
- Run a smoke test that constructs the full IoServer stack before deployment.
- Check interface imports — two similarly named MessageComponentInterface classes exist under Ratchet\ and Ratchet\WebSocket\.
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
- $request can not be null
- $request can not be null
- Invalid WAMP message format
- Invalid Topic, must be a string
- Invalid WAMP message type
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)