coollabsio/coolify · warning · Exception
The following file is a file on the server, but you are tryi
Error message
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.
What it means
Thrown by LocalFileVolume::saveStorageOnServer() (app/Models/LocalFileVolume.php:261) when the model is marked is_directory=true but the resolved path on the destination server already exists as a regular file (test -f returns OK). Coolify self-heals before throwing: it cats the file content (or stores a TOO_LARGE placeholder if it exceeds the size limit), flips is_directory to false, saves, and dispatches FileStorageChanged — then throws this Exception to tell the operator about the mismatch. So the error is informational; the model has already been reconciled to reality.
Source
Thrown at app/Models/LocalFileVolume.php:261
$path = $workdir.$path;
}
// Validate and escape resolved path (may differ from fs_path if relative)
validateShellSafePath($path, 'storage path');
$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");View on GitHub (pinned to 70b9acc424)
Solutions
- Nothing is broken — refresh the model/UI ($fileVolume->refresh()) and re-save; the record now correctly says is_directory=false with the file's content loaded.
- If you truly need a directory there, remove the file on the server (rm <path> via SSH or instant_remote_process) and save the storage again.
- Give the directory storage a different fs_path that does not collide with an existing file.
Example fix
// before $fileVolume->is_directory = true; $fileVolume->saveStorageOnServer(); // throws: server path is a plain file // after — accept the self-heal, or clear the collision first // instant_remote_process(['rm '.escapeshellarg($path)], $server, false); $fileVolume->refresh(); // model was auto-corrected to is_directory=false $fileVolume->is_directory = true; $fileVolume->saveStorageOnServer();
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-check server-side state before saving a directory-flagged storage
$escapedPath = escapeshellarg($resolvedPath);
$isFile = instant_remote_process(["test -f {$escapedPath} && echo OK || echo NOK"], $server);
if ($isFile === 'OK' && $fileVolume->is_directory) {
// path collision: choose another fs_path or delete the file first
} Try / catch
try {
$fileVolume->saveStorageOnServer();
} catch (\Exception $e) {
if (str_contains($e->getMessage(), 'you are trying to mark it as a directory')) {
// Model was auto-corrected to is_directory=false; refresh UI and re-save
$fileVolume->refresh();
return;
}
throw $e;
} Prevention
- Pick unique fs_path values per storage definition; avoid two storages targeting the same path with different types.
- Treat this exception as a reconcile notice, not a failure — always refresh() the model afterwards.
- If a directory is required, clear the colliding file on the server before saving.
When it happens
Trigger: Toggling a file storage entry to 'directory' when fs_path already holds a plain file on the server; saving a storage definition whose path collides with a file created by the app or by a previous storage entry; two storage definitions pointing at the same path with different types.
Common situations: Editing the storage type dropdown on an existing mount without clearing the old file; apps that replace a mounted directory with a file (e.g. a bind-mounted config the app overwrites); copied/renamed services reusing fs_path values.
Related errors
- The following file is a directory on the server, but you are
- Pre-deployment command: Could not find a valid container. Is
- Post-deployment command: Could not find a valid container. I
- ScheduledTaskJob failed: No valid container was found. Is th
- Failed to store SSH key: {message}
AI-assisted analysis of coollabsio/coolify@70b9acc424 (2026-08-17).
Data as JSON: /api/errors/6e4e392f895f700a.
Report an issue: GitHub.