dnoegel/php-xdg-base-dir · error · RuntimeException
XDG_RUNTIME_DIR was not set
Error message
XDG_RUNTIME_DIR was not set
What it means
This RuntimeException is thrown by DcborgDev\Xdg\Xdg::getRuntimeDir() when the XDG_RUNTIME_DIR environment variable is not set and the $strict argument is true. XDG_RUNTIME_DIR is where per-user runtime files (sockets, locks, pids) should live, and the XDG Base Directory spec requires it to be set by the session/login manager. In non-strict mode the library silently falls back to a temp-directory path instead.
Solutions
- Export XDG_RUNTIME_DIR before running PHP (e.g. export XDG_RUNTIME_DIR=/run/user/$(id -u)) or set it via putenv() in the bootstrap.
- Call getRuntimeDir(false) to use the library's /tmp fallback instead of throwing.
- On systemd services add RuntimeDirectory= or Environment=XDG_RUNTIME_DIR=/run/user/%U to the unit.
- In containers/Docker, set the env var explicitly (ENV XDG_RUNTIME_DIR=/tmp/runtime) and create the directory with correct 0700 permissions.
Example fix
// before $dir = $xdg->getRuntimeDir(true); // throws if XDG_RUNTIME_DIR unset // after $dir = $xdg->getRuntimeDir(false); // falls back to sys_get_temp_dir()/...
Defensive patterns
Strategy: fallback
Validate before calling
if (getenv('XDG_RUNTIME_DIR') === false || getenv('XDG_RUNTIME_DIR') === '') {
putenv('XDG_RUNTIME_DIR=' . sys_get_temp_dir() . '/runtime-' . getmypid());
}
$dir = $xdg->getRuntimeDir(true); Type guard
function hasXdgRuntimeDir(): bool {
$v = getenv('XDG_RUNTIME_DIR');
return is_string($v) && $v !== '';
} Try / catch
try {
$dir = $xdg->getRuntimeDir(true);
} catch (\RuntimeException $e) {
if ($e->getMessage() === 'XDG_RUNTIME_DIR was not set') {
$dir = sys_get_temp_dir() . '/myapp-runtime';
if (!is_dir($dir)) { mkdir($dir, 0700, true); }
} else {
throw $e;
}
} Prevention
- Check getenv('XDG_RUNTIME_DIR') early at application bootstrap and fail fast with a clear message.
- Prefer getRuntimeDir(false) in non-interactive contexts (cron, containers, CI).
- Set Environment=XDG_RUNTIME_DIR or RuntimeDirectory= in systemd unit files for services.
- Set the variable explicitly in Dockerfile/CI env so workers inherit it.
When it happens
Trigger: Calling (new \DcborgDev\Xdg\Xdg())->getRuntimeDir(true) (or any call that defaults $strict to true) via getenv('XDG_RUNTIME_DIR') when that env var is unset in the PHP process environment.
Common situations: Running PHP outside a full desktop session (cron jobs, systemd units without RuntimeDirectory, Docker containers, SSH non-login shells, web-server/PHP-FPM processes) where no login manager exports XDG_RUNTIME_DIR; also CLI workers or CI environments that stripped environment variables.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
AI-assisted analysis of dnoegel/php-xdg-base-dir@12f5b94710 (2026-09-16).
Data as JSON: /api/errors/90f3621011146599.
Report an issue: GitHub.
Appendix: source
Thrown at src/Xdg.php:93
/**
* @return string
*/
public function getHomeCacheDir()
{
$path = getenv('XDG_CACHE_HOME') ?: $this->getHomeDir() . DIRECTORY_SEPARATOR . '.cache';
return $path;
}
public function getRuntimeDir($strict=true)
{
if ($runtimeDir = getenv('XDG_RUNTIME_DIR')) {
return $runtimeDir;
}
if ($strict) {
throw new \RuntimeException('XDG_RUNTIME_DIR was not set');
}
$fallback = sys_get_temp_dir() . DIRECTORY_SEPARATOR . self::RUNTIME_DIR_FALLBACK . getenv('USER');
$create = false;
if (!is_dir($fallback)) {
mkdir($fallback, 0700, true);
}
$st = lstat($fallback);
# The fallback must be a directory
if (!$st['mode'] & self::S_IFDIR) {
rmdir($fallback);
$create = true;
} elseif ($st['uid'] != $this->getUid() ||
$st['mode'] & (self::S_IRWXG | self::S_IRWXO)View on GitHub (pinned to 12f5b94710)