{"record":{"id":"816dd3b75b7cf132","repo":"PHPOffice/PhpSpreadsheet","slug":"file-filename-does-not-exist","errorCode":null,"errorMessage":"File $filename does not exist","messagePattern":"File \\$filename does not exist","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Writer\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Writer/Xlsx/ContentTypes.php","lineNumber":294,"sourceCode":"    /**\n     * Get image mime type.\n     *\n     * @param string $filename Filename\n     *\n     * @return string Mime Type\n     */\n    private function getImageMimeType(string $filename): string\n    {\n        if (Preg::isMatch('~^data:(image/[^;]+);base64,~', $filename, $matches)) {\n            return $matches[1];\n        }\n        if (File::fileExists($filename)) {\n            $image = getimagesize($filename);\n\n            return image_type_to_mime_type((is_array($image) && count($image) >= self::$three) ? $image[2] : 0);\n        }\n\n        throw new WriterException(\"File $filename does not exist\");\n    }\n\n    /**\n     * Write Default content type.\n     *\n     * @param string $partName Part name\n     * @param string $contentType Content type\n     */\n    private function writeDefaultContentType(XMLWriter $objWriter, string $partName, string $contentType): void\n    {\n        if ($partName != '' && $contentType != '') {\n            // Write content type\n            $objWriter->startElement('Default');\n            $objWriter->writeAttribute('Extension', $partName);\n            $objWriter->writeAttribute('ContentType', $contentType);\n            $objWriter->endElement();\n        } else {\n            throw new WriterException('Invalid parameters passed.');","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Writer/Xlsx/ContentTypes.php#L276-L312","documentation":"While building [Content_Types].xml for Xlsx output, every drawing image must be mapped to a MIME type. ContentTypes::getImageMimeType() first matches a 'data:image/...;base64,' URI, then requires an existing readable file (File::fileExists); if neither holds it throws with the stored path. Typical cause: a Drawing whose image file was deleted, moved, or never existed by the time save() runs.","triggerScenarios":"$drawing = new Drawing(); $drawing->setPath($tmpPath); ... then unlink($tmpPath) or queue/session temp-file cleanup removes it before $writer->save('out.xlsx'); or a path with a typo/nonexistent location.","commonSituations":"Queued jobs that process uploads after PHP's tmp-dir cleanup; flows that save twice with a cleanup in between; images uploaded to object storage and deleted locally right after being referenced.","solutions":["Keep image files on disk until after save() completes (unlink only after save returns)","Copy user-supplied images to your own storage and point the Drawing at that copy","Before save, iterate the sheet's drawings and verify is_file($drawing->getPath())","Use a MemoryDrawing or a data: URI path so no external file is needed (the code explicitly supports data: URIs)"],"exampleFix":"// before\n$drawing->setPath($uploadedTmpPath);\n$writer->save('out.xlsx');\nunlink($uploadedTmpPath); // risky if save is called again later\n\n// after\n$localCopy = storage_path('images/' . basename($uploadedTmpPath));\ncopy($uploadedTmpPath, $localCopy);\n$drawing->setPath($localCopy);\n$writer->save('out.xlsx');","handlingStrategy":"validation","validationCode":"/** All drawing images must exist (or be data URIs) before Xlsx save. */\nfunction drawingImagesExist(Spreadsheet $spreadsheet): bool\n{\n    foreach ($spreadsheet->getAllSheets() as $sheet) {\n        foreach ($sheet->getDrawingCollection() as $drawing) {\n            if ($drawing instanceof \\PhpOffice\\PhpSpreadsheet\\Worksheet\\Drawing) {\n                $path = $drawing->getPath();\n                if (!str_starts_with($path, 'data:') && !is_file($path)) {\n                    return false;\n                }\n            }\n        }\n    }\n\n    return true;\n}\n\nif (!drawingImagesExist($spreadsheet)) {\n    throw new RuntimeException('A drawing references a missing image file; export aborted');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $writer->save('out.xlsx');\n} catch (\\PhpOffice\\PhpSpreadsheet\\Writer\\Exception $e) {\n    if (preg_match('/File (.+) does not exist/u', $e->getMessage(), $m)) {\n        // $m[1] names the missing image; drop that drawing and retry once\n        removeDrawingByPath($spreadsheet, $m[1]);\n        $writer->save('out.xlsx');\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Keep image files alive until save() returns; unlink in a finally block after save","Copy uploaded/temporary images to durable storage before attaching them to drawings","For ephemeral images, embed a data: URI path or use MemoryDrawing so no file dependency exists"],"tags":["phpspreadsheet","xlsx","image","drawing","missing-file"],"backgroundTag":"missing-image-file","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}