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

  1. Set an explicit non-empty fs_path (e.g. '/data/app.db' or './config'), never '/', '.', '..' or blank.
  2. If a directory is actually intended, mark the storage as a directory so the model and server state agree.
  3. 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

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


AI-assisted analysis of coollabsio/coolify@70b9acc424 (2026-08-17). Data as JSON: /api/errors/e211fd5c991293c6. Report an issue: GitHub.