PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Writer\Exception
File $filename does not exist
Error message
File $filename does not exist
What it means
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.
Source
Thrown at src/PhpSpreadsheet/Writer/Xlsx/ContentTypes.php:294
/**
* Get image mime type.
*
* @param string $filename Filename
*
* @return string Mime Type
*/
private function getImageMimeType(string $filename): string
{
if (Preg::isMatch('~^data:(image/[^;]+);base64,~', $filename, $matches)) {
return $matches[1];
}
if (File::fileExists($filename)) {
$image = getimagesize($filename);
return image_type_to_mime_type((is_array($image) && count($image) >= self::$three) ? $image[2] : 0);
}
throw new WriterException("File $filename does not exist");
}
/**
* Write Default content type.
*
* @param string $partName Part name
* @param string $contentType Content type
*/
private function writeDefaultContentType(XMLWriter $objWriter, string $partName, string $contentType): void
{
if ($partName != '' && $contentType != '') {
// Write content type
$objWriter->startElement('Default');
$objWriter->writeAttribute('Extension', $partName);
$objWriter->writeAttribute('ContentType', $contentType);
$objWriter->endElement();
} else {
throw new WriterException('Invalid parameters passed.');View on GitHub (pinned to 65b080eef4)
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)
Example fix
// before
$drawing->setPath($uploadedTmpPath);
$writer->save('out.xlsx');
unlink($uploadedTmpPath); // risky if save is called again later
// after
$localCopy = storage_path('images/' . basename($uploadedTmpPath));
copy($uploadedTmpPath, $localCopy);
$drawing->setPath($localCopy);
$writer->save('out.xlsx'); Defensive patterns
Strategy: validation
Validate before calling
/** All drawing images must exist (or be data URIs) before Xlsx save. */
function drawingImagesExist(Spreadsheet $spreadsheet): bool
{
foreach ($spreadsheet->getAllSheets() as $sheet) {
foreach ($sheet->getDrawingCollection() as $drawing) {
if ($drawing instanceof \PhpOffice\PhpSpreadsheet\Worksheet\Drawing) {
$path = $drawing->getPath();
if (!str_starts_with($path, 'data:') && !is_file($path)) {
return false;
}
}
}
}
return true;
}
if (!drawingImagesExist($spreadsheet)) {
throw new RuntimeException('A drawing references a missing image file; export aborted');
} Try / catch
try {
$writer->save('out.xlsx');
} catch (\PhpOffice\PhpSpreadsheet\Writer\Exception $e) {
if (preg_match('/File (.+) does not exist/u', $e->getMessage(), $m)) {
// $m[1] names the missing image; drop that drawing and retry once
removeDrawingByPath($spreadsheet, $m[1]);
$writer->save('out.xlsx');
} else {
throw $e;
}
} Prevention
- 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
When it happens
Trigger: $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.
Common situations: 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.
Related errors
- A Worksheet has already been assigned. Drawings can only exi
- Item is not a drawing
- Could not find zip member $zipfile
- Unsupported image type in comment background. Supported type
- Invalid protocol for linked drawing
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/816dd3b75b7cf132.
Report an issue: GitHub.