{"record":{"id":"e934a61a8828acde","repo":"ratchetphp/Ratchet","slug":"bad-encoding-unicode-character-did-not-match-expected-value","errorCode":null,"errorMessage":"Bad encoding, unicode character ✓ did not match expected value. Ensure charset UTF-8 and check ini val mbstring.func_autoload","messagePattern":"Bad encoding, unicode character ✓ did not match expected value\\. Ensure charset UTF-8 and check ini val mbstring\\.func_autoload","errorType":"exception","errorClass":"DomainException","httpStatus":null,"severity":"error","filePath":"src/Ratchet/WebSocket/WsServer.php","lineNumber":83,"sourceCode":"    /**\n     * @param \\Ratchet\\WebSocket\\MessageComponentInterface|\\Ratchet\\MessageComponentInterface $component Your application to run with WebSockets\n     * @note If you want to enable sub-protocols have your component implement WsServerInterface as well\n     */\n    public function __construct(ComponentInterface $component) {\n        if ($component instanceof MessageComponentInterface) {\n            $this->msgCb = function(ConnectionInterface $conn, MessageInterface $msg) {\n                $this->delegate->onMessage($conn, $msg);\n            };\n        } elseif ($component instanceof DataComponentInterface) {\n            $this->msgCb = function(ConnectionInterface $conn, MessageInterface $msg) {\n                $this->delegate->onMessage($conn, $msg->getPayload());\n            };\n        } else {\n            throw new \\UnexpectedValueException('Expected instance of \\Ratchet\\WebSocket\\MessageComponentInterface or \\Ratchet\\MessageComponentInterface');\n        }\n\n        if (bin2hex('✓') !== 'e29c93') {\n            throw new \\DomainException('Bad encoding, unicode character ✓ did not match expected value. Ensure charset UTF-8 and check ini val mbstring.func_autoload');\n        }\n\n        $this->delegate    = $component;\n        $this->connections = new \\SplObjectStorage;\n\n        $this->closeFrameChecker   = new CloseFrameChecker;\n\n        if (self::isRFC6455v03()) {\n            $this->handshakeNegotiator = new ServerNegotiator(new RequestVerifier);\n        } else {\n            $this->handshakeNegotiator = new ServerNegotiator(new RequestVerifier, new HttpFactory);\n        }\n\n        $this->handshakeNegotiator->setStrictSubProtocolCheck(true);\n\n        if ($component instanceof WsServerInterface) {\n            $this->handshakeNegotiator->setSupportedSubProtocols($component->getSubProtocols());\n        }","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/ratchetphp/Ratchet/blob/e621c6c40bf684bbbb877102416ad5303d05a9cc/src/Ratchet/WebSocket/WsServer.php#L65-L101","documentation":"WsServer's constructor performs a runtime sanity check that the literal UTF-8 character '✓' encodes to the expected bytes (e29c93). If bin2hex output differs, the file or PHP runtime is not operating on UTF-8, which would corrupt WebSocket payloads, so a DomainException is thrown at startup.","triggerScenarios":"Constructing WsServer while the source file has been re-encoded (e.g. saved as ISO-8859-1 or a BOM/encoding mangling changed the '✓' bytes), or PHP ini settings/extensions altering string encoding semantics (historic mbstring.func_overload misconfiguration).","commonSituations":"Deployment pipelines or editors re-encoding WsServer.php; rsync/FTP transfer with character translation; servers with mbstring.func_overload=2 enabled (legacy) affecting string functions.","solutions":["Ensure WsServer.php is stored and served as UTF-8: re-download from the official release or `composer install` fresh.","Check `php -i | grep mbstring.func_overload` and set mbstring.func_overload to 0 (remove the ini override) — note func_overload is removed in PHP 7.4+, so the real cause is usually file encoding.","Fix the editor/toolchain that re-encodes the file (set files encoding to UTF-8 without BOM) and redeploy."],"exampleFix":"; php.ini — before\nmbstring.func_overload = 2\n; after\nmbstring.func_overload = 0","handlingStrategy":"validation","validationCode":"if (bin2hex('✓') !== 'e29c93') {\n    // detect encoding corruption before constructing WsServer\n    error_log('Non-UTF-8 runtime/file encoding detected');\n}\n$ws = new \\Ratchet\\WebSocket\\WsServer($app);","typeGuard":null,"tryCatchPattern":"try {\n    $ws = new \\Ratchet\\WebSocket\\WsServer($app);\n} catch (\\DomainException $e) {\n    // fatal environment problem: abort boot with a clear message\n    exit('Server files must be UTF-8; check mbstring.func_overload and file encoding');\n}","preventionTips":["Deploy vendor files as-is (composer install on the server or download archives) — never re-encode .php sources.","Verify editor/toolchain saves files as UTF-8 without BOM.","Keep mbstring.func_overload at 0 on legacy PHP; confirm with `php -i`.","Checksum vendor files after rsync/FTP transfers that might translate characters."],"tags":["php","encoding","utf-8"],"backgroundTag":"invalid-config-value","analyzedSha":"e621c6c40bf684bbbb877102416ad5303d05a9cc","analyzedAt":"2026-09-16T00:13:27.878Z","contentChangedAt":"2026-09-16T00:13:27.878Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}