{"id":"1a2ea1249921e5f2","repo":"guzzle/guzzle","slug":"unable-to-save-file-s","errorCode":null,"errorMessage":"Unable to save file %s","messagePattern":"Unable to save file (.+?)","errorType":"exception","errorClass":"\\RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Cookie/FileCookieJar.php","lineNumber":110,"sourceCode":"    {\n        $json = [];\n        /** @var SetCookie $cookie */\n        foreach ($this as $cookie) {\n            if (CookieJar::shouldPersist($cookie, $this->storeSessionCookies)) {\n                $data = $cookie->toArray();\n                $data['HostOnly'] = $cookie->getHostOnly();\n                $json[] = $data;\n            }\n        }\n\n        try {\n            $jsonStr = \\json_encode($json, \\JSON_HEX_TAG | \\JSON_THROW_ON_ERROR);\n        } catch (\\JsonException $e) {\n            throw new \\RuntimeException('Unable to encode cookie data', 0, $e);\n        }\n\n        if (false === \\file_put_contents($filename, $jsonStr, \\LOCK_EX)) {\n            throw new \\RuntimeException(\\sprintf('Unable to save file %s', DiagnosticValue::escape($filename)));\n        }\n\n        // Best-effort: restrict the cookie file to the owner so persisted\n        // cookies are not world-readable.\n        @\\chmod($filename, 0600);\n    }\n\n    /**\n     * Load cookies from a JSON formatted file.\n     *\n     * Old cookies are kept unless overwritten by newly loaded ones.\n     * Cookie records are constructed before any are passed to setCookie().\n     *\n     * @param string $filename Cookie file to load.\n     *\n     * @throws \\RuntimeException if the file cannot be loaded or is invalid\n     */\n    public function load(string $filename): void","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/guzzle/guzzle/blob/9b200fc5805036b331d6031199880dadecae0275/src/Cookie/FileCookieJar.php#L92-L128","documentation":"Thrown by FileCookieJar::save() when file_put_contents() returns false, meaning the cookie JSON could not be written. The %s is the escaped filename (DiagnosticValue::escape is used to keep control bytes out of the message). This is an I/O failure: the path is unwritable, the directory does not exist, permissions are denied, or the disk is full.","triggerScenarios":"Constructing `new FileCookieJar('/nonexistent/cookies.json')` then letting the destructor fire save(); pointing the jar at a directory that is not writable; running the script as a user without write permission to the file; SELinux/AppArmor denying the write; read-only filesystem.","commonSituations":"Deploying to a container where the target path is a read-only mounted volume; web user (www-data) lacking write permission on the cookies file; passing a relative path that resolves to an unexpected cwd; disk-full conditions.","solutions":["Verify the directory exists and is writable by the PHP process user: is_dir(dirname($path)) && is_writable(dirname($path)).","Use an absolute path under a known-writable directory (e.g. sys_get_temp_dir() or a dedicated var/ dir).","Pre-create the file and chmod 0600 it; ensure the web user owns it.","Catch \\RuntimeException in __destruct context by calling save() explicitly in a try/catch (the destructor itself cannot meaningfully throw to the caller)."],"exampleFix":"// before\n$jar = new FileCookieJar('/var/lock/cookies.json'); // not writable by app\n\n// after\n$path = dirname(__DIR__).'/var/cookies.json';\n@touch($path); @chmod($path, 0600);\n$jar = new FileCookieJar($path);","handlingStrategy":"validation","validationCode":"$dir = dirname($path);\nif (!is_dir($dir) || !is_writable($dir)) {\n    throw new RuntimeException(\"Cookie dir not writable: $dir\");\n}\n@touch($path); @chmod($path, 0600);\n$jar = new FileCookieJar($path);","typeGuard":"function cookieFileIsWritable(string $path): bool\n{\n    $dir = dirname($path);\n    return is_dir($dir) && is_writable($dir)\n        && (!file_exists($path) || is_writable($path));\n}","tryCatchPattern":"try {\n    $jar->save($path);\n} catch (\\RuntimeException $e) {\n    if (str_starts_with($e->getMessage(), 'Unable to save file')) {\n        // fall back to a temp dir or in-memory jar\n    }\n}","preventionTips":["Pre-create and chmod 0600 the cookie file from your deployment script.","Use an absolute path under a known-writable directory.","Call save() explicitly (not just __destruct) so failures surface where you can handle them.","Verify the PHP process user owns/has write access to the file."],"tags":["cookies","filesystem","permissions","io","runtimeexception"],"analyzedSha":"9b200fc5805036b331d6031199880dadecae0275","analyzedAt":"2026-08-04T21:24:26.648Z","schemaVersion":2}