{"record":{"id":"5f221b612b78a91d","repo":"PHPOffice/PhpSpreadsheet","slug":"registered-readers-must-implement-phpoffice-phpspr","errorCode":null,"errorMessage":"Registered readers must implement PhpOffice\\PhpSpreadsheet\\Reader\\IReader","messagePattern":"Registered readers must implement PhpOffice\\\\PhpSpreadsheet\\\\Reader\\\\IReader","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Reader\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/IOFactory.php","lineNumber":283,"sourceCode":"     */\n    public static function registerWriter(string $writerType, string $writerClass): void\n    {\n        if (!is_a($writerClass, IWriter::class, true)) {\n            throw new Writer\\Exception('Registered writers must implement ' . IWriter::class);\n        }\n\n        self::$writers[$writerType] = $writerClass;\n    }\n\n    /**\n     * Register a reader with its type and class name.\n     *\n     * @param class-string<IReader> $readerClass\n     */\n    public static function registerReader(string $readerType, string $readerClass): void\n    {\n        if (!is_a($readerClass, IReader::class, true)) {\n            throw new Reader\\Exception('Registered readers must implement ' . IReader::class);\n        }\n\n        self::$readers[$readerType] = $readerClass;\n    }\n\n    /**\n     * @return array<string, class-string<IReader>>\n     *\n     * @internal\n     *\n     * @codeCoverageIgnore\n     */\n    public static function getReaders(): array\n    {\n        return self::$readers;\n    }\n}\n","sourceCodeStart":265,"sourceCodeEnd":301,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/IOFactory.php#L265-L301","documentation":"IOFactory::registerReader() validates the class-string with is_a($readerClass, IReader::class, true) before storing it. Registering a class that does not implement PhpOffice\\PhpSpreadsheet\\Reader\\IReader - nonexistent class names, namespace typos, wrong base class - throws at registration time rather than at load time.","triggerScenarios":"IOFactory::registerReader('MyFormat', MyReader::class) where MyReader is a plain class; passing an instance instead of the class-string; migrating PHPExcel-era readers that implemented PHPExcel_Reader_IAbstract.","commonSituations":"Custom readers for in-house file formats; registrations driven by plugin configuration; upgrades from PHPExcel where interface names changed.","solutions":["Implement the full IReader interface (canRead(), load(), listWorksheetInfo(), etc.) or extend Reader\\BaseReader","Fix the namespace/class-string and pass the ::class constant","Pre-check with is_a($class, IReader::class, true) when the class name comes from user/config input"],"exampleFix":"// before\nclass MyReader { /* no IReader */ }\nIOFactory::registerReader('MyFormat', MyReader::class);\n\n// after\nclass MyReader extends \\PhpOffice\\PhpSpreadsheet\\Reader\\BaseReader\n{\n    // implement canRead() and loadSpreadsheetFromFile()\n}\nIOFactory::registerReader('MyFormat', MyReader::class);","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"/** Guard before IOFactory::registerReader(). */\nfunction isRegisterableReader(string $class): bool\n{\n    return class_exists($class)\n        && is_a($class, \\PhpOffice\\PhpSpreadsheet\\Reader\\IReader::class, true);\n}\n\nif (!isRegisterableReader($readerClass)) {\n    throw new InvalidArgumentException(\"$readerClass must implement IReader\");\n}\nIOFactory::registerReader('MyFormat', $readerClass);","tryCatchPattern":"try {\n    IOFactory::registerReader('MyFormat', $configuredReaderClass);\n} catch (\\PhpOffice\\PhpSpreadsheet\\Reader\\Exception $e) {\n    error_log(\"Skipping reader registration: {$e->getMessage()}\");\n}","preventionTips":["Extend Reader\\BaseReader rather than implementing IReader piecemeal","Use ClassName::class for registrations; validate config-sourced names with is_a() first","During PHPExcel migrations, remember interface names changed (IReader lives in the Reader namespace)"],"tags":["phpspreadsheet","iofactory","reader","plugin-registration","interface"],"backgroundTag":"invalid-plugin-registration","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}