flarum/framework · error · RuntimeException
Failed to open file at $filePath
Error message
Failed to open file at $filePath
What it means
The GDPR extension's storeExport() opens the generated export file with fopen(..., 'r') and throws a RuntimeException when fopen returns false — i.e. the file could not be opened for reading. The export data is then streamed into the user's storage disk via writeStream. The failing path is included in the message.
Solutions
- Verify the export file exists and is readable before storing: is_file() + is_readable(), and fix generation/paths accordingly
- Fix filesystem permissions so the PHP process user can read the file and its directory
- Check open_basedir / disable_functions restrictions in php.ini that may block fopen on the temp path
- Ensure the export generation step completes and returns the correct file path
Example fix
// before
$ext->storeExport($export, $tmpPath); // file missing
// after
if (!is_readable($tmpPath)) { throw new RuntimeException("Export missing: $tmpPath"); }
$ext->storeExport($export, $tmpPath); Defensive patterns
Strategy: try-catch
Validate before calling
if (!is_file($filePath) || !is_readable($filePath)) { throw new \RuntimeException("Export file missing or unreadable: $filePath"); } Try / catch
try { $manager->storeExport($export, $filePath); } catch (\RuntimeException $e) { Log::error($e->getMessage()); abort(500, 'Could not store GDPR export'); } Prevention
- Check is_readable() on temp export files before storing
- Keep export temp files in a path not blocked by open_basedir
- Clean up/export promptly to avoid races deleting the file
When it happens
Trigger: Calling storeExport($export, $filePath) with a $filePath that doesn't exist, isn't readable by the PHP user, or whose directory denies access — any case where fopen returns false.
Common situations: Export generator wrote the temp file to a different tmp dir (open_basedir restrictions); permissions changed after generation; path typo or file deleted between generation and storing; safe_mode/open_basedir blocking reads on shared hosting.
Understand the failure class
Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.
Related errors
- Invalid erasure mode: $mode
- Erase requests cannot be confirmed by different users.
- This erasure request has already been processed.
AI-assisted analysis of flarum/framework@4b939f6853 (2026-09-15).
Data as JSON: /api/errors/de887463f6b6d0ff.
Report an issue: GitHub.
Appendix: source
Thrown at extensions/gdpr/src/StorageManager.php:37
public function __construct(protected Factory $factory)
{
$this->filesystem = $this->factory->disk('gdpr-export');
}
/**
* Stores the export on the disk.
*
* @param Export $export
* @param string $filePath
*
* @return void
*/
public function storeExport(Export $export, string $filePath): void
{
$handle = fopen($filePath, 'r');
if ($handle === false) {
throw new \RuntimeException("Failed to open file at $filePath");
}
$this->filesystem->writeStream($this->storageFilename($export), $handle);
fclose($handle);
}
/**
* @param Export $export
*
* @return resource|null The path resource or null on failure.
*/
public function getStoredExport(Export $export)
{
return $this->filesystem->readStream($this->storageFilename($export));
}
/**View on GitHub (pinned to 4b939f6853)