guzzle/guzzle · error · RuntimeException
Unable to save file
Error message
Unable to save file %s
What it means
save() calls file_put_contents($filename, $jsonStr, LOCK_EX) and treats a false return as a hard failure. The path is escaped with DiagnosticValue::escape so control bytes in the path cannot tamper with the exception message. Any IO-level write failure (missing directory, unwritable target, disk full, lock contention) lands here.
Solutions
- Ensure the parent directory exists and is writable: mkdir(dirname($path), 0700, true) before constructing the jar.
- Verify the runtime user owns or can write the target file.
- Check disk space and inode usage on the target filesystem.
- Use an absolute path; confirm the path is not on a read-only mount.
Example fix
// before
new FileCookieJar('/var/run/app/cookies.json');
// after
$path = '/var/run/app/cookies.json';
@mkdir(dirname($path), 0700, true);
new FileCookieJar($path); Defensive patterns
Strategy: validation
Validate before calling
// Verify the directory is writable before constructing the jar.
function ensureWritableFile(string $path): void {
$dir = \dirname($path);
if (!\is_dir($dir)) {
\mkdir($dir, 0700, true);
}
if (!\is_writable($dir)) {
throw new \RuntimeException("Cookie dir not writable: {$dir}");
}
} Try / catch
try {
$jar = new FileCookieJar($path);
$jar->save($path);
} catch (\RuntimeException $e) {
// IO failure; degrade gracefully (e.g. fall back to in-memory jar)
} Prevention
- Pre-create the cookie directory with mkdir(..., 0700, true).
- Confirm the PHP runtime user owns or can write the target path.
- Use absolute paths and check disk space on the target filesystem.
When it happens
Trigger: Constructor path points at a directory that does not exist or is not writable by the PHP runtime user; the file is on a read-only filesystem; LOCK_EX could not be acquired; out of disk or inodes.
Common situations: Containerized deployments where the cookie path is on an unmounted volume; per-user directories that were never created; permissions reset by a deployment; PHP-FPM running as www-data while the target dir is owned by root.
Related errors
- Invalid cookie file
- Unable to encode cookie data
- Unable to load file
- GuzzleHttp\Cookie\FileCookieJar should never be unserialized
- Unable to encode cookie data
AI-assisted analysis of guzzle/guzzle@d1cbca7697 (2026-08-06).
Data as JSON: /api/errors/1a2ea1249921e5f2.
Report an issue: GitHub.
Appendix: source
Thrown at src/Cookie/FileCookieJar.php:110
{
$json = [];
/** @var SetCookie $cookie */
foreach ($this as $cookie) {
if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {
$data = $cookie->toArray();
$data['HostOnly'] = $cookie->getHostOnly();
$json[] = $data;
}
}
try {
$jsonStr = \json_encode($json, \JSON_HEX_TAG | \JSON_THROW_ON_ERROR);
} catch (\JsonException $e) {
throw new \RuntimeException('Unable to encode cookie data', 0, $e);
}
if (false === \file_put_contents($filename, $jsonStr, \LOCK_EX)) {
throw new \RuntimeException(\sprintf('Unable to save file %s', DiagnosticValue::escape($filename)));
}
// Best-effort: restrict the cookie file to the owner so persisted
// cookies are not world-readable.
@\chmod($filename, 0600);
}
/**
* Load cookies from a JSON formatted file.
*
* Old cookies are kept unless overwritten by newly loaded ones.
* Cookie records are constructed before any are passed to setCookie().
*
* @param string $filename Cookie file to load.
*
* @throws \RuntimeException if the file cannot be loaded or is invalid
*/
public function load(string $filename): voidView on GitHub (pinned to d1cbca7697)