walkor/workerman · error · RuntimeException
Invalid protocol scheme '$scheme'
Error message
Invalid protocol scheme '$scheme'
What it means
parseSocketAddress() splits the Worker's $socketName on the first ':' and treats the part before it as a protocol scheme. If the scheme is not one of the built-in transports (tcp, udp, unix, ssl), Workerman maps it to a PHP class name (Protocols\Scheme). Before doing that it validates the scheme against ^[a-zA-Z][a-zA-Z0-9]*$ and throws 'Invalid protocol scheme' when it contains characters that are illegal in a class name. This exists both as a config sanity check and so arbitrary strings cannot reach class resolution.
Source
Thrown at src/Worker.php:2562
}
}
}
/**
* Parse local socket address.
*/
protected function parseSocketAddress(): ?string
{
if (!$this->socketName) {
return null;
}
// Get the application layer communication protocol and listening address.
[$scheme, $address] = explode(':', $this->socketName, 2);
// Check application layer protocol class.
if (!isset(self::BUILD_IN_TRANSPORTS[$scheme])) {
// Validate scheme contains only safe characters for class name resolution.
if (!preg_match('/^[a-zA-Z][a-zA-Z0-9]*$/', $scheme)) {
throw new RuntimeException("Invalid protocol scheme '$scheme'");
}
$scheme = ucfirst($scheme);
$this->protocol = 'Protocols\\' . $scheme;
if (!class_exists($this->protocol)) {
$this->protocol = "Workerman\\Protocols\\$scheme";
if (!class_exists($this->protocol)) {
throw new RuntimeException("class \\Protocols\\$scheme not exist");
}
}
if (!isset(self::BUILD_IN_TRANSPORTS[$this->transport])) {
throw new RuntimeException('Bad worker->transport ' . var_export($this->transport, true));
}
} else if ($this->transport === 'tcp') {
$this->transport = $scheme;
}
//local socket
return self::BUILD_IN_TRANSPORTS[$this->transport] . ":" . $address;View on GitHub (pinned to 1391112a61)
Solutions
- Fix the scheme to be a letter-first alphanumeric word that matches your protocol class name, e.g. 'MyTextProtocol://0.0.0.0:8080' for class Protocols\MyTextProtocol.
- If you meant a standard protocol, use the builtin scheme spelling instead: http, https, ws, wss (these resolve to Workerman\Protocols\Http/Http2? no — Http, Ws classes) or transports tcp/udp/unix/ssl.
- Rename the protocol class/file to StudlyCase alphanumerics (e.g. Protocols/MyTextProtocol.php) so scheme and class name line up.
Example fix
// before: hyphenated scheme cannot map to a PHP class name
$worker = new Worker('my-text-protocol://0.0.0.0:8080');
// after: letter-first alphanumeric scheme matching Protocols\MyTextProtocol
$worker = new Worker('MyTextProtocol://0.0.0.0:8080'); Defensive patterns
Strategy: validation
Validate before calling
$socketName = 'MyProto://0.0.0.0:8080';
$scheme = strtok($socketName, ':') ?: '';
if (!preg_match('/^[a-zA-Z][a-zA-Z0-9]*$/', $scheme)) {
throw new InvalidArgumentException("Bad protocol scheme '$scheme' (must be letter-first alphanumeric)");
}
$worker = new Worker($socketName); Type guard
function isValidWorkermanScheme(string $socketName): bool
{
$scheme = strtok($socketName, ':') ?: '';
$builtin = ['tcp', 'udp', 'unix', 'ssl', 'http', 'https', 'ws', 'wss', 'text', 'frame'];
return in_array(strtolower($scheme), $builtin, true)
|| (bool) preg_match('/^[a-zA-Z][a-zA-Z0-9]*$/', $scheme);
} Prevention
- Name custom protocols in StudlyCase alphanumerics only (MyTextProtocol, not my-text-protocol).
- Centralize listen addresses in one config file and lint the scheme format in tests.
When it happens
Trigger: Constructing a Worker whose listen address has a non-builtin scheme containing hyphens, dots, underscores, a leading digit, or non-ASCII characters, e.g. new Worker('my-text-protocol://0.0.0.0:8080'), new Worker('foo.bar://...'), new Worker('2fast://...'), or a mistyped scheme like 'http -' or an empty scheme (':8080').
Common situations: Naming a custom protocol class with kebab-case (My-Text-Protocol) instead of StudlyCase; copying a protocol name from a URL/queue config that uses '+' or '-' separators (ws+tls, ssl-ws); a typo or stray character before the colon in $worker->listen.
Related errors
- Bad worker->transport ${var_export($this->transport, true)}
- Bad remoteAddress
- Invalid protocol scheme '$scheme'
- class \Protocols\$scheme not exist
- Invalid protocol scheme '$scheme'
AI-assisted analysis of walkor/workerman@1391112a61 (2026-08-21).
Data as JSON: /api/errors/0f2875d86e3de74f.
Report an issue: GitHub.