getgrav/grav · warning · RuntimeException
Unknown error
Error message
Unknown error
What it means
Folder::delete() falls back to error_get_last() when doDelete() fails without capturing a specific path failure; if PHP recorded no error either, you get the terminal RuntimeException 'Unknown error'. It means recursive deletion returned false from operations whose diagnostics were fully suppressed — the informative paths of error [10] were exhausted. It is rare and usually accompanies exotic filesystem states where even the fallback has nothing to report.
Source
Thrown at system/src/Grav/Common/Filesystem/Folder.php:435
{
if (!is_dir($target)) {
return false;
}
$failure = null;
$success = self::doDelete($target, $include_target, $failure);
if (!$success) {
// Prefer the precise reason captured at the first failing path
// (which file/dir, the OS error, and any owner/process mismatch).
// Fall back to the last PHP error, then to a generic message.
if (null !== $failure) {
throw new RuntimeException($failure);
}
$error = error_get_last();
throw new RuntimeException($error['message'] ?? 'Unknown error');
}
// Make sure that the change will be detected when caching.
if ($include_target) {
@touch(dirname($target));
} else {
@touch($target);
}
return $success;
}
/**
* @param string $folder
* @return void
* @throws RuntimeException
*/
public static function mkdir($folder)View on GitHub (pinned to 6040efed04)
Solutions
- Re-run the deletion immediately — transient races (concurrent purge of the same tree) often clear themselves
- Manually inspect the target path: ls -la, file owner, mount type (mount | grep <path>) to spot vanishing or foreign-mount directories
- Instrument around the call: enable PHP error logging to file (log_errors=On, error_log set) so suppressed warnings are captured even when error_get_last() is empty
- If the tree is on NFS/FUSE/samba, test deleting one file by hand as the same user to reproduce the underlying OS error
Defensive patterns
Strategy: retry
Try / catch
try {
Folder::delete($dir);
} catch (RuntimeException $e) {
if ($e->getMessage() === 'Unknown error') {
// diagnostics were suppressed — one immediate retry covers races; then investigate manually
Folder::delete($dir);
} else {
throw $e;
}
} Prevention
- Enable PHP error logging (log_errors, error_log) so suppressed warnings are on disk even when error_get_last() is empty
- Avoid concurrent purges of the same directory (stagger cron jobs)
- Treat repeat 'Unknown error' as an environment smell — test manual deletion on the exact path as the same user
When it happens
Trigger: scandir() failing on a directory that vanished mid-iteration; suppressed unlink/rmdir failures that did not populate error_get_last() (errors captured by earlier handlers); filesystems with unusual failure modes (FUSE mounts, sandboxed containers); race conditions where another process removes files during the recursive walk.
Common situations: Two concurrent requests purging the same cache directory; mounted network storage with intermittent failures; opcache/anti-virus intercepting unlinks on Windows; container filesystem overlays with permission quirks.
Related errors
- Unable to %s: %s
- Unable to create directory: %s
- Creating directory failed for {filepath}
- Opening file for writing failed on error {$message}
- Failed to save file {filepath}
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/8c302b2b2ec6ff3d.
Report an issue: GitHub.