symfony/http-foundation · error · RuntimeException
Session Storage was not able to create directory
Error message
Session Storage was not able to create directory "%s".
What it means
NativeFileSessionHandler ensures the session base directory exists; when the directory is missing, it attempts a recursive mkdir with 0777 permissions. If mkdir fails and the directory still does not exist, a RuntimeException is thrown because the handler cannot store session files.
Solutions
- Create the directory manually with correct ownership/permissions (e.g. mkdir -p /var/lib/php/sessions && chown www-data:www-data ...).
- Point session.save_path to an existing, writable directory.
- Grant the PHP process user write permission on the target directory's parent chain.
- Check that the filesystem/volume is writable (not mounted read-only) and the path is valid.
Example fix
// before
$handler = new NativeFileSessionHandler('/var/lib/php/sessions'); // dir missing, PHP user cannot create it
// after (shell pre-provisioning)
// mkdir -p /var/lib/php/sessions && chown www-data:www-data /var/lib/php/sessions
$handler = new NativeFileSessionHandler('/var/lib/php/sessions'); Defensive patterns
Strategy: try-catch
Validate before calling
$baseDir = $savePath ?? ini_get('session.save_path');
if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0777, true) && !is_dir($baseDir)) {
throw new \RuntimeException("Cannot create session dir: $baseDir");
} Try / catch
try {
$handler = new NativeFileSessionHandler($savePath);
} catch (\RuntimeException $e) {
// provision the directory or switch to an alternative handler
} Prevention
- Provision session directories in deployment/Docker images with correct ownership.
- Run PHP workers as a user with write access to the save path.
- Avoid read-only root filesystems without a writable tmpfs for sessions.
- Health-check directory writability at application boot.
When it happens
Trigger: Constructing the handler with a $savePath (or ini session.save_path) pointing to a nonexistent directory that cannot be created — typically due to filesystem permissions, a read-only volume, or an invalid parent path.
Common situations: Deployments where /var/lib/php/sessions was removed or never created; Docker containers running as non-root with an unwritable path; misconfigured '2;/nonexistent-root/...' save paths; read-only container filesystems.
Understand the failure class
Background: mkdir permission denied (EACCES): failed to create directory errors explained — this error's family across 32 libraries.
Related errors
- The session handler " " does not support clearing all…
- You must provide the "database" and "collection" option for…
- Invalid argument $savePath
- " " requires PDO error mode attribute be set to throw…
- Creating the session table is currently not implemented for…
AI-assisted analysis of symfony/http-foundation@5aea19cd67 (2026-09-13).
Data as JSON: /api/errors/97a2de2a44adf32f.
Report an issue: GitHub.
Appendix: source
Thrown at Session/Storage/Handler/NativeFileSessionHandler.php:48
*
* @throws \InvalidArgumentException On invalid $savePath
* @throws \RuntimeException When failing to create the save directory
*/
public function __construct(?string $savePath = null)
{
$baseDir = $savePath ??= \ini_get('session.save_path');
if ($count = substr_count($savePath, ';')) {
if ($count > 2) {
throw new \InvalidArgumentException(\sprintf('Invalid argument $savePath \'%s\'.', $savePath));
}
// characters after last ';' are the path
$baseDir = ltrim(strrchr($savePath, ';'), ';');
}
if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir, 0o777, true) && !is_dir($baseDir)) {
throw new \RuntimeException(\sprintf('Session Storage was not able to create directory "%s".', $baseDir));
}
if ($savePath !== \ini_get('session.save_path')) {
ini_set('session.save_path', $savePath);
}
if ('files' !== \ini_get('session.save_handler')) {
ini_set('session.save_handler', 'files');
}
}
public function clear(): void
{
$savePath = \ini_get('session.save_path');
if (str_contains($savePath, ';')) {
$savePath = ltrim(strrchr($savePath, ';'), ';');
}
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($savePath, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY);View on GitHub (pinned to 5aea19cd67)