{"record":{"id":"fcdf6c4722ff6710","repo":"PHPOffice/PhpSpreadsheet","slug":"file-filename-does-not-exist-or-is-not-readable","errorCode":null,"errorMessage":"File \"$filename\" does not exist or is not readable.","messagePattern":"File \"\\$filename\" does not exist or is not readable\\.","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Reader\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Shared/File.php","lineNumber":165,"sourceCode":"        if (\n            Preg::IsMatch('~^phar://~i', $filename)\n            || (Preg::isMatch('/^([\\w.\\s\\x00-\\x1f]+):/', $filename) && !Preg::isMatch('/^([\\w.]+):/', $filename))\n            || Preg::isMatch('~^[\\w.]+://.*phar:~is', $filename)\n        ) {\n            throw new Exception(\n                \"Disallowed stream wrapper used for {$filename}\"\n            );\n        }\n    }\n\n    /**\n     * Assert that given path is an existing file and is readable, otherwise throw exception.\n     */\n    public static function assertFile(string $filename, string $zipMember = ''): void\n    {\n        self::prohibitWrappers($filename);\n        if (!is_file($filename) || !is_readable($filename)) {\n            throw new ReaderException('File \"' . $filename . '\" does not exist or is not readable.');\n        }\n\n        if ($zipMember !== '') {\n            $zipfile = \"zip://$filename#$zipMember\";\n            if (!self::fileExists($zipfile)) {\n                // Has the file been saved with Windoze directory separators rather than unix?\n                $zipfile = \"zip://$filename#\" . str_replace('/', '\\\\', $zipMember);\n                if (!self::fileExists($zipfile)) {\n                    throw new ReaderException(\"Could not find zip member $zipfile\");\n                }\n            }\n        }\n    }\n\n    /**\n     * Same as assertFile, except return true/false and don't throw Exception.\n     * Will nevertheless throw if filename uses invalid protocol, e.g. phar.\n     */","sourceCodeStart":147,"sourceCodeEnd":183,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Shared/File.php#L147-L183","documentation":"File::assertFile() runs prohibitWrappers() then is_file()/is_readable(); any failure throws this ReaderException (src/PhpSpreadsheet/Shared/File.php:165). Every reader's load() path calls it (error 180's flow shows it before canRead), making it the first gate for loading from disk — the file must exist as a regular file and be readable by the PHP process.","triggerScenarios":"load('missing.xlsx'); a relative path resolved against a different working directory (CLI vs web server); permissions denying the runtime user; open_basedir restrictions on the path; the file deleted between upload handling and read; passing a directory name.","commonSituations":"Moved/renamed uploads; scaffolding with a wrong base directory; running as www-data while files belong to another user; symlinked storage mounts; queue workers whose cwd differs from the web entrypoint.","solutions":["Resolve to an absolute path before loading and fail loudly if realpath() returns false","Gate with file_exists() && is_readable() and surface your own error message including the resolved path","Fix ownership/permissions or adjust open_basedir for the runtime user","For stream or user-uploaded content, persist to a temp file first and load that path"],"exampleFix":"// before\n$spreadsheet = \\PhpOffice\\PhpSpreadsheet\\IOFactory::load($request['path']); // relative/untrusted\n\n// after\n$path = realpath($request['path']);\nif ($path === false || !is_readable($path)) {\n    throw new \\InvalidArgumentException(\"Spreadsheet file not found or unreadable: {$request['path']}\");\n}\n$spreadsheet = \\PhpOffice\\PhpSpreadsheet\\IOFactory::load($path);","handlingStrategy":"validation","validationCode":"function assertSpreadsheetReadable(string $path): string\n{\n    $real = realpath($path);\n    if ($real === false || !is_file($real) || !is_readable($real)) {\n        throw new \\InvalidArgumentException(\"Spreadsheet missing/unreadable: $path\");\n    }\n\n    return $real;\n}\n\n$spreadsheet = \\PhpOffice\\PhpSpreadsheet\\IOFactory::load(assertSpreadsheetReadable($path));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Convert user- or config-supplied paths to absolute (realpath) before loading","Verify the runtime user can read the storage mount in staging smoke tests","Move uploaded files to your own storage path and read from there, not from tmp names that may be cleaned up"],"tags":["filesystem","file-not-found","permissions","paths"],"backgroundTag":"file-not-found","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}