{"record":{"id":"4ad04f206df88273","repo":"PHPOffice/PhpSpreadsheet","slug":"unable-to-identify-a-reader-for-this-file","errorCode":null,"errorMessage":"Unable to identify a reader for this file","messagePattern":"Unable to identify a reader for this file","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Reader\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/IOFactory.php","lineNumber":218,"sourceCode":"            // Let's see if we are lucky\n            if ($reader->canRead($filename)) {\n                return $reader;\n            }\n        }\n\n        // If we reach here then \"lucky guess\" didn't give any result\n        // Try walking through all the options in self::$readers (or the selected subset)\n        foreach ($testReaders as $readerType => $class) {\n            //    Ignore our original guess, we know that won't work\n            if ($readerType !== $guessedReader) {\n                $reader = self::createReader($readerType, $testReaders);\n                if ($reader->canRead($filename)) {\n                    return $reader;\n                }\n            }\n        }\n\n        throw new Reader\\Exception('Unable to identify a reader for this file');\n    }\n\n    /**\n     * Guess a reader type from the file extension, if any.\n     */\n    private static function getReaderTypeFromExtension(string $filename): ?string\n    {\n        $pathinfo = pathinfo($filename);\n        if (!isset($pathinfo['extension'])) {\n            return null;\n        }\n\n        return match (strtolower($pathinfo['extension'])) {\n            // Excel (OfficeOpenXML) Spreadsheet\n            'xlsx',\n            // Excel (OfficeOpenXML) Macro Spreadsheet (macros will be discarded)\n            'xlsm',\n            // Excel (OfficeOpenXML) Template","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/IOFactory.php#L200-L236","documentation":"IOFactory::load()/identify() first guesses a reader from the file extension, then falls back to trying canRead() on every registered reader. If the guessed reader rejects the file and so does every other one, this exception is thrown: the file is not recognizable as any supported spreadsheet format. It is a content-signature failure, not a permissions error.","triggerScenarios":"IOFactory::load('report.xyz') with an unrecognized format; a password-protected/encrypted .xlsx (canRead fails); an HTML error page or empty file named .xlsx; a truncated upload.","commonSituations":"User uploads with spoofed or missing extensions; encrypted workbooks (PhpSpreadsheet cannot decrypt); API responses saved as .xlsx that are actually JSON/HTML; CSVs with unusual encodings failing the Csv canRead heuristic.","solutions":["Open with the concrete reader you expect (e.g. new Reader\\Xlsx()) to get a clearer error","Verify the file signature first: ZIP 'PK' header for .xlsx, OLE header for .xls","Reject password-protected workbooks early with a clear user-facing message","Validate uploads by content type, not just extension"],"exampleFix":"// before\n$spreadsheet = IOFactory::load($uploadedPath);\n\n// after\n$reader = new \\PhpOffice\\PhpSpreadsheet\\Reader\\Xlsx();\nif (!$reader->canRead($uploadedPath)) {\n    throw new InvalidArgumentException('Not a readable XLSX file');\n}\n$spreadsheet = $reader->load($uploadedPath);","handlingStrategy":"validation","validationCode":"/** Cheap signature check before IOFactory::load(). */\nfunction looksLikeSpreadsheet(string $path): bool\n{\n    $fh = fopen($path, 'rb');\n    if ($fh === false) {\n        return false;\n    }\n    $head = (string) fread($fh, 8);\n    fclose($fh);\n\n    return str_starts_with($head, 'PK')        // zip: xlsx/ods\n            || str_starts_with($head, \"\\xd0\\xcf\\x11\\xe0\") // OLE: legacy xls\n            || trim($head) === ''                 // possible csv/sylk\n            || stripos($head, '<') !== false;     // html/xml-ish\n}\n\nif (!looksLikeSpreadsheet($uploadedPath)) {\n    throw new InvalidArgumentException('Uploaded file is not a spreadsheet');\n}\n$spreadsheet = IOFactory::load($uploadedPath);","typeGuard":null,"tryCatchPattern":"try {\n    $spreadsheet = IOFactory::load($uploadedPath);\n} catch (\\PhpOffice\\PhpSpreadsheet\\Reader\\Exception $e) {\n    if (str_contains($e->getMessage(), 'Unable to identify a reader')) {\n        // user-facing error: the file is not a supported spreadsheet (or is encrypted)\n        throw new UploadRejectException('Unsupported or corrupted file. Please upload XLSX, XLS, ODS or CSV.', 0, $e);\n    }\n    throw $e;\n}","preventionTips":["Validate upload magic bytes (PK for zip-based formats) before handing files to IOFactory","Reject password-protected workbooks early - PhpSpreadsheet cannot decrypt them","For known formats, use the concrete reader directly for clearer failures"],"tags":["phpspreadsheet","iofactory","reader","file-format","autodetect"],"backgroundTag":"unsupported-file-format","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}