walkor/workerman · error · RuntimeException
can not save pid to ${static::$pidFile}
Error message
can not save pid to ${static::$pidFile} What it means
On startup the master process writes its PID to Worker::$pidFile (default under sys_get_temp_dir()) so stop/reload/status commands can find it. file_put_contents() returning false means the file could not be written - missing directory, permission denied, read-only filesystem, or disk full - and Workerman aborts because process management would be broken.
Source
Thrown at src/Worker.php:1506
if (function_exists('posix_isatty') && posix_isatty(2)) {
ob_start(function (string $string) {
file_put_contents(static::$stdoutFile, $string, FILE_APPEND);
}, 1);
}
}
/**
* Save pid.
*/
protected static function saveMasterPid(): void
{
if (DIRECTORY_SEPARATOR !== '/') {
return;
}
static::$masterPid = posix_getpid();
if (false === file_put_contents(static::$pidFile, static::$masterPid)) {
throw new RuntimeException('can not save pid to ' . static::$pidFile);
}
}
/**
* Get all pids of worker processes.
*
* @return array
*/
protected static function getAllWorkerPids(): array
{
$pidArray = [];
foreach (static::$pidMap as $workerPidArray) {
foreach ($workerPidArray as $workerPid) {
$pidArray[$workerPid] = $workerPid;
}
}
return $pidArray;
}View on GitHub (pinned to 1391112a61)
Solutions
- Point the pid file at a writable location for the run user, e.g. Worker::$pidFile = '/var/run/myapp/workerman.pid' after creating and chown-ing that directory
- Check the directory exists and the user can write: 'sudo -u appuser touch <dir>/test'
- Remove a stale pid file left by a root run: 'sudo rm <pidFile>'
Example fix
// before Worker::$pidFile = '/var/run/workerman.pid'; // /var/run not writable by app user Worker::runAll(); // 'can not save pid to /var/run/workerman.pid' // after Worker::$pidFile = '/var/run/myapp/workerman.pid'; // provisioned once at deploy: mkdir -p /var/run/myapp && chown appuser /var/run/myapp Worker::runAll();
Defensive patterns
Strategy: validation
Validate before calling
$pidFile = '/var/run/myapp/workerman.pid';
$dir = dirname($pidFile);
if (!is_dir($dir) || !is_writable($dir)) {
throw new RuntimeException("pid directory $dir missing or not writable");
}
Worker::$pidFile = $pidFile; Prevention
- Create and chown the pid directory in the deploy script for the exact user that runs Workerman
- Clean stale pid files when switching the run user (e.g. moving from root to an app user)
When it happens
Trigger: Custom Worker::$pidFile = '/var/run/workerman.pid' with /var/run not writable by the runtime user; the target directory was deleted; a stale pid file owned by root while the service now runs as an unprivileged user on a read-only-ish path; disk full.
Common situations: Hardening a service to run as non-root without adjusting the pidFile path; switching between root and app-user starts; container images with read-only root filesystems; /tmp cleaned by tmpfiles.d while using the default path assumptions.
Related errors
- Bad remoteAddress
- Invalid protocol scheme '$scheme'
- class \Protocols\$scheme not exist
- Invalid protocol scheme '$scheme'
- class \Protocols\$scheme not exist
AI-assisted analysis of walkor/workerman@1391112a61 (2026-08-21).
Data as JSON: /api/errors/778a9ec9c08c86f0.
Report an issue: GitHub.