{"record":{"id":"70fa913c24e313f1","repo":"walkor/workerman","slug":"errmsg","errorCode":null,"errorMessage":"${errMsg}","messagePattern":"\\$\\{errMsg\\}","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"src/Worker.php","lineNumber":2462,"sourceCode":"        }\n\n        if (!$this->mainSocket) {\n\n            $localSocket = $this->parseSocketAddress();\n\n            // Flag.\n            $flags = $this->transport === 'udp' ? STREAM_SERVER_BIND : STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;\n            $errNo = 0;\n            $errMsg = '';\n            // SO_REUSEPORT.\n            if ($this->reusePort && DIRECTORY_SEPARATOR !== '\\\\') {\n                stream_context_set_option($this->socketContext, 'socket', 'so_reuseport', 1);\n            }\n\n            // Create an Internet or Unix domain server socket.\n            $this->mainSocket = stream_socket_server($localSocket, $errNo, $errMsg, $flags, $this->socketContext);\n            if (!$this->mainSocket) {\n                throw new RuntimeException($errMsg);\n            }\n\n            if ($this->transport === 'ssl') {\n                stream_socket_enable_crypto($this->mainSocket, false);\n            } elseif ($this->transport === 'unix') {\n                $socketFile = substr($localSocket, 7);\n                if ($this->user) {\n                    chown($socketFile, $this->user);\n                }\n                if ($this->group) {\n                    chgrp($socketFile, $this->group);\n                }\n            }\n\n            // Try to open keepalive for tcp and disable Nagle algorithm.\n            if (function_exists('socket_import_stream') && self::BUILD_IN_TRANSPORTS[$this->transport] === 'tcp') {\n                set_error_handler(static fn (): bool => true);\n                $socket = socket_import_stream($this->mainSocket);","sourceCodeStart":2444,"sourceCodeEnd":2480,"githubUrl":"https://github.com/walkor/workerman/blob/1391112a61d23020e11e7b89f17050f6cfaea431/src/Worker.php#L2444-L2480","documentation":"During Worker->run() the listening socket is created with stream_socket_server() over the configured listen address (tcp://host:port, unix://path). On failure Workerman throws the OS-provided $errMsg verbatim - typical texts are 'Address already in use', 'Permission denied', 'Cannot assign requested address'. This is the classic bind/listen failure and always occurs at worker startup before the event loop runs.","triggerScenarios":"Another process holds the port (previous instance not stopped, dev copy running); binding a port < 1024 as non-root; listen address referencing an IPv6 address on a host without IPv6 or a non-local IP; unix socket file already exists (stale socket from a crashed run); SELinux/AppArmor denying the bind.","commonSituations":"Starting the service twice; crash left a stale unix socket file; deploying as non-root on port 80/443; misconfigured 0.0.0.0 vs specific interface addresses; SELinux-enabled hosts blocking non-standard ports for the service context.","solutions":["Find and stop the occupant: 'ss -ltnp | grep :PORT' (or lsof -i :PORT), kill it or enable reusePort ('Worker->reusePort = true') when running multiple instances intentionally","For ports below 1024 run with privileges, use setcap, or put a reverse proxy in front and listen on a high port","Remove a stale unix socket before start (rm /path/app.sock) or add unlink logic in onWorkerStart; fix the listen string to a valid address your host actually owns"],"exampleFix":"# before\nphp start.php start\n# RuntimeException: Address already in use\n\n# after\nss -ltnp | grep :8080        # find old master\nkill <old-master-pid>         # or: php start.php stop\nphp start.php start\n\n# for intentional multi-instance listeners:\n# $worker->reusePort = true;","handlingStrategy":"validation","validationCode":"$port = 8080;\n$probe = @fsockopen('127.0.0.1', $port, $errNo, $errStr, 1);\nif ($probe !== false) {\n    fclose($probe);\n    throw new RuntimeException(\"port $port already in use - stop the old instance or enable reusePort\");\n}\nif ($port < 1024 && (function_exists('posix_getuid') ? posix_getuid() : 0) !== 0) {\n    throw new RuntimeException(\"port $port needs privileges or a reverse proxy\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    $worker = new Worker('http://0.0.0.0:8080');\n    $worker->reusePort = true; // allow parallel listeners\n    Worker::runAll();\n} catch (RuntimeException $e) {\n    // message is the OS bind error, e.g. 'Address already in use'\n    fwrite(STDERR, 'listen failed: ' . $e->getMessage() . PHP_EOL);\n    exit(1);\n}","preventionTips":["Always stop the old instance before starting (php start.php stop) or enable reusePort for multi-instance setups","For unix transports, unlink the stale socket file in onWorkerStart or a pre-start script","Bind ports >= 1024 for non-root services and front them with nginx/caddy"],"tags":["php","workerman","socket","bind","listen","port-in-use","startup"],"backgroundTag":"address-in-use","analyzedSha":"1391112a61d23020e11e7b89f17050f6cfaea431","analyzedAt":"2026-08-21T02:05:46.744Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}