coollabsio/coolify · error · Exception
The following file is a directory on the server, but you are
Error message
The following file is a directory on the server, but you are trying to mark it as a file. <br><br>Please delete the directory on the server or mark it as directory.
What it means
Thrown by LocalFileVolume::saveStorageOnServer() (app/Models/LocalFileVolume.php:266) when the model is marked is_directory=false but the path on the server is a directory, and the resolved path is one of the dangerous roots '/', '.', '..', or empty. Coolify refuses the destructive fix-up it would normally do (rm -fr + touch) for these roots, flips is_directory to true, saves, and throws to inform the operator. For non-root directory paths the code instead silently replaces the directory with an empty file — this error only fires for the root-path cases.
Source
Thrown at app/Models/LocalFileVolume.php:266
$escapedPath = escapeshellarg($path);
$isFile = instant_remote_process(["test -f {$escapedPath} && echo OK || echo NOK"], $server);
$isDir = instant_remote_process(["test -d {$escapedPath} && echo OK || echo NOK"], $server);
if ($isFile === 'OK' && $this->is_directory) {
if ($this->remoteFileExceedsLimit($escapedPath, $server)) {
$this->content = self::TOO_LARGE_PLACEHOLDER;
} else {
$this->content = instant_remote_process(["cat {$escapedPath}"], $server, false);
}
$this->is_directory = false;
$this->save();
FileStorageChanged::dispatch(data_get($server, 'team_id'));
throw new \Exception('The following file is a file on the server, but you are trying to mark it as a directory. Please delete the file on the server or mark it as directory.');
} elseif ($isDir === 'OK' && ! $this->is_directory) {
if ($path === '/' || $path === '.' || $path === '..' || $path === '' || str($path)->isEmpty() || is_null($path)) {
$this->is_directory = true;
$this->save();
throw new \Exception('The following file is a directory on the server, but you are trying to mark it as a file. <br><br>Please delete the directory on the server or mark it as directory.');
}
instant_remote_process([
"rm -fr {$escapedPath}",
"touch {$escapedPath}",
], $server, false);
FileStorageChanged::dispatch(data_get($server, 'team_id'));
}
if ($isDir === 'NOK' && ! $this->is_directory) {
$chmod = data_get($this, 'chmod');
$chown = data_get($this, 'chown');
if ($content) {
$content = base64_encode($content);
$commands->push("echo '$content' | base64 -d | tee {$escapedPath} > /dev/null");
} else {
$commands->push("touch {$escapedPath}");
}
$commands->push("chmod +x {$escapedPath}");
if ($chown) {View on GitHub (pinned to 70b9acc424)
Solutions
- Set an explicit non-empty fs_path (e.g. '/data/app.db' or './config'), never '/', '.', '..' or blank.
- If a directory is actually intended, mark the storage as a directory so the model and server state agree.
- Refresh and re-save after the throw — the model has already been auto-corrected to is_directory=true for this path.
Example fix
// before $fileVolume->fs_path = '.'; $fileVolume->is_directory = false; $fileVolume->saveStorageOnServer(); // throws: '.' resolves to a directory // after $fileVolume->fs_path = './data'; $fileVolume->saveStorageOnServer();
Defensive patterns
Strategy: validation
Validate before calling
// Reject unsafe paths before saving a file-type storage
$fsPath = trim((string) $fileVolume->fs_path);
if (in_array($fsPath, ['/', '.', '..', ''], true) || $fileVolume->fs_path === null) {
throw new \InvalidArgumentException('fs_path must be an explicit, non-root path.');
} Try / catch
try {
$fileVolume->saveStorageOnServer();
} catch (\Exception $e) {
if (str_contains($e->getMessage(), 'you are trying to mark it as a file')) {
// fs_path resolved to a directory root; the model was flipped to is_directory=true
$fileVolume->refresh();
return 'Set an explicit file path instead of a directory root.';
}
throw $e;
} Prevention
- Never use '/', '.', '..' or empty strings as fs_path; always give an explicit path segment.
- Mark storages as directories when the target is (or will be) a directory so the destructive rm -fr branch is never needed.
When it happens
Trigger: A file storage with is_directory=false whose fs_path resolves to '/', '.', '..', '' or a path string that trims to empty — e.g. fs_path set to '.' (relative to workdir) while the workdir itself is the target. The test -d check succeeds, the root-path guard matches, the model is corrected to is_directory=true, then the exception is raised.
Common situations: Entering '.', '/', or blank in the storage path field; relative fs_path values like './' that resolve to the container workdir; importing service templates whose storage paths were left as '.'.
Related errors
- The following file is a file on the server, but you are tryi
- Failed to store SSH key: {message}
- Failed to open lock file for SSH key: {$lockFile}
- Failed to acquire lock for SSH key: {$keyLocation}
- Failed to write SSH key to filesystem. Check disk space and
AI-assisted analysis of coollabsio/coolify@70b9acc424 (2026-08-17).
Data as JSON: /api/errors/e211fd5c991293c6.
Report an issue: GitHub.