PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
Could not create temporary file
Error message
Could not create temporary file
What it means
File::temporaryFilename() wraps tempnam(sysGetTempDir(), 'phpspreadsheet') and throws when tempnam returns false, i.e. the system temporary directory could not be used (src/PhpSpreadsheet/Shared/File.php:134). Save paths that need scratch space — CSV/PDF writers, large spreadsheet writes — all funnel through it, so a broken temp dir breaks every save.
Source
Thrown at src/PhpSpreadsheet/Shared/File.php:134
$path = sys_get_temp_dir();
if (self::$useUploadTempDirectory) {
// use upload-directory when defined to allow running on environments having very restricted
// open_basedir configs
if (ini_get('upload_tmp_dir') !== false) {
if ($temp = ini_get('upload_tmp_dir')) {
if (file_exists($temp)) {
$path = $temp;
}
}
}
}
return realpath($path) ?: '';
}
public static function temporaryFilename(): string
{
return tempnam(self::sysGetTempDir(), 'phpspreadsheet') ?: throw new Exception('Could not create temporary file');
}
/**
* Blocks phar:// and similar RCE-bearing wrappers.
* Note that many protocols, including http and zip, will already
* return false for is_file.
* A whitelist of protocols may be added if needed in future.
* data: is intentionally allowed (see #4823); callers needing strict
* on-disk-only semantics must validate $filename themselves.
*/
public static function prohibitWrappers(string $filename): void
{
if (
Preg::IsMatch('~^phar://~i', $filename)
|| (Preg::isMatch('/^([\w.\s\x00-\x1f]+):/', $filename) && !Preg::isMatch('/^([\w.]+):/', $filename))
|| Preg::isMatch('~^[\w.]+://.*phar:~is', $filename)
) {
throw new Exception(View on GitHub (pinned to 65b080eef4)
Solutions
- Point TMPDIR at a writable directory before saving: putenv('TMPDIR=/var/app/tmp') (and ensure it exists with the right ownership), or fix upload_tmp_dir/sys temp config
- Free space or inodes on the temp filesystem
- Adjust open_basedir to include the temp directory
- Run PHP under a user with write access to the temp dir
Example fix
// before
$writer = new \PhpOffice\PhpSpreadsheet\Writer\Xlsx($spreadsheet);
$writer->save('php://output'); // throws: Could not create temporary file
// after
$tmp = '/var/app/tmp';
if (!is_dir($tmp)) { mkdir($tmp, 0770, true); }
putenv('TMPDIR=' . $tmp);
$writer->save('php://output'); Defensive patterns
Strategy: fallback
Validate before calling
use PhpOffice\PhpSpreadsheet\Shared\File;
function ensureTempDirAvailable(): void
{
$dir = sys_get_temp_dir();
if (!is_dir($dir) || !is_writable($dir)) {
$alt = __DIR__ . '/../storage/tmp';
if (!is_dir($alt)) { mkdir($alt, 0770, true); }
putenv('TMPDIR=' . $alt); // tempnam() uses this via sysGetTempDir()
}
} Prevention
- Health-check the temp dir in deployment smoke tests (is_writable + free space)
- Mount a writable emptyDir/tmpfs on read-only containers and set TMPDIR
- Monitor disk and inode usage on export-heavy services
- Run PHP under a user with temp-dir write access
When it happens
Trigger: The temp directory is full (bytes or inodes), missing, or unwritable for the PHP runtime user; open_basedir excludes sys_getTempDir(); containers run with a read-only root filesystem and no writable TMPDIR; upload_tmp_dir misconfigured to a nonexistent path.
Common situations: Kubernetes containers with readOnlyRootFilesystem and no emptyDir mount; shared hosting with restrictive open_basedir; disk exhausted after repeated large exports; CI environments with tiny tmpfs.
Related errors
- Could not open file {filename} for reading.
- File "$filename" does not exist or is not readable.
- Unable to get contents of $filename
- Unable to open php://memory
- Code page $codePage not implemented on this system.
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/016426e2839191e2.
Report an issue: GitHub.