{"record":{"id":"8f14b90dae324614","repo":"walkor/workerman","slug":"class-protocols-scheme-not-exist","errorCode":null,"errorMessage":"class \\Protocols\\$scheme not exist","messagePattern":"class \\\\Protocols\\\\\\$scheme not exist","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Connection/AsyncTcpConnection.php","lineNumber":222,"sourceCode":"                : $this->remoteHost . ':' . $this->remotePort;\n        }\n\n        $this->id = $this->realId = self::$idRecorder++;\n        if (PHP_INT_MAX === self::$idRecorder) {\n            self::$idRecorder = 0;\n        }\n        // Check application layer protocol class.\n        if (!isset(self::BUILD_IN_TRANSPORTS[$scheme])) {\n            // Validate scheme contains only safe characters for class name resolution.\n            if (!preg_match('/^[a-zA-Z][a-zA-Z0-9]*$/', $scheme)) {\n                throw new RuntimeException(\"Invalid protocol scheme '$scheme'\");\n            }\n            $scheme = ucfirst($scheme);\n            $this->protocol = '\\\\Protocols\\\\' . $scheme;\n            if (!class_exists($this->protocol)) {\n                $this->protocol = \"\\\\Workerman\\\\Protocols\\\\$scheme\";\n                if (!class_exists($this->protocol)) {\n                    throw new RuntimeException(\"class \\\\Protocols\\\\$scheme not exist\");\n                }\n            }\n        } else {\n            $this->transport = self::BUILD_IN_TRANSPORTS[$scheme];\n        }\n\n        // For statistics.\n        ++self::$statistics['connection_count'];\n        $this->maxSendBufferSize = self::$defaultMaxSendBufferSize;\n        $this->maxPackageSize = self::$defaultMaxPackageSize;\n        $this->socketContext = $socketContext;\n        static::$connections[$this->realId] = $this;\n        $this->context = new stdClass;\n    }\n\n    /**\n     * Reconnect.\n     *","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/walkor/workerman/blob/1391112a61d23020e11e7b89f17050f6cfaea431/src/Connection/AsyncTcpConnection.php#L204-L240","documentation":"The scheme was alphanumeric but is not a built-in transport, so Workerman tried to load an application-layer protocol class: first '\\Protocols\\<Scheme>' then '\\Workerman\\Protocols\\<Scheme>'. Neither could be autoloaded, so the constructor aborts. This is how workerman resolves schemes like http, ws, text, frame and any user-defined protocol.","triggerScenarios":"new AsyncTcpConnection('myproto://host:80') without a Protocols\\Myproto class; typo in a known protocol name, e.g. 'frame2://' or 'etxt://' instead of 'text://'; protocol class exists but the 'Protocols' namespace is not registered in composer's PSR-4 autoload; class filename casing does not match the ucfirst()-derived class name.","commonSituations":"New project where the custom protocol file was not created yet or sits in the wrong directory; composer.json missing the {\"Protocols\\\\\": \"Protocols/\"} PSR-4 mapping; forgot to run 'composer dump-autoload' after adding the mapping; on case-sensitive filesystems the file must be named exactly like the resolved class (e.g. Myproto.php).","solutions":["Create the protocol class, e.g. Protocols/Myproto.php with namespace Protocols and class Myproto implementing the protocol interface (input/output methods)","Make sure composer.json autoloads the namespace: \"autoload\": {\"psr-4\": {\"Protocols\\\\\": \"Protocols/\"}} and run 'composer dump-autoload'","If you meant a stock protocol, use its exact scheme: http://, ws://, text://, frame://"],"exampleFix":"// before\n// config: 'myproto://127.0.0.1:9000' but no class exists\n$conn = new AsyncTcpConnection('myproto://127.0.0.1:9000'); // throws class \\Protocols\\Myproto not exist\n\n// after\n// Protocols/Myproto.php\nnamespace Protocols;\nclass Myproto\n{\n    public static function input(string $buffer, $connection): int { /* ... */ return strlen($buffer); }\n    public static function decode(string $buffer, $connection) { return $buffer; }\n    public static function encode($data, $connection): string { return (string)$data; }\n}\n// composer.json: \"autoload\": {\"psr-4\": {\"Protocols\\\\\": \"Protocols/\"}} then: composer dump-autoload","handlingStrategy":"validation","validationCode":"$scheme = 'myproto'; // from config\n$builtin = ['tcp','udp','unix','ssl','sslv2','sslv3','tls'];\n$known = in_array(strtolower($scheme), $builtin, true)\n    || class_exists('\\\\Protocols\\\\' . ucfirst($scheme))\n    || class_exists('\\\\Workerman\\\\Protocols\\\\' . ucfirst($scheme));\nif (!$known) {\n    throw new InvalidArgumentException(\"Protocol '$scheme' has no class; define Protocols\\\\\" . ucfirst($scheme));\n}\n$conn = new AsyncTcpConnection(\"$scheme://host:port\");","typeGuard":null,"tryCatchPattern":"try { $conn = new AsyncTcpConnection($address); } catch (RuntimeException $e) { if (str_contains($e->getMessage(), 'not exist')) { /* log config error, skip endpoint */ } throw $e; }","preventionTips":["Register the Protocols PSR-4 mapping in composer.json on day one and run composer dump-autoload after adding protocol classes","Name protocol classes exactly as ucfirst of the scheme and match file casing on case-sensitive filesystems","Run a startup smoke check that class_exists() for every configured scheme before serving traffic"],"tags":["php","workerman","protocol","autoloading"],"backgroundTag":"class-not-found","analyzedSha":"1391112a61d23020e11e7b89f17050f6cfaea431","analyzedAt":"2026-08-21T02:05:46.744Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}