coollabsio/coolify · error · DeploymentException

Command execution failed (exit code {$process_result->exitCo

Error message

Command execution failed (exit code {$process_result->exitCode()}): {$redactedCommand}
Error: {$error}

What it means

Coolify runs every deployment step over SSH on the destination server via the ExecuteRemoteCommand trait (Symfony Process wrapping an SSH multiplexed command). When the process finishes with a non-zero exit code and ignore_errors is false, it throws DeploymentException containing the exit code, the command with secrets redacted via redact_sensitive_info(), and the stderr output (falling back to stdout, then to 'Command failed with no error output'). ApplicationDeploymentJob catches it, marks the deployment queue row as failed, and preserves the logs. A special exit code 69420 instead means 'Deployment cancelled by user'.

Source

Thrown at app/Traits/ExecuteRemoteCommand.php:243

        $process_result = $process->wait();
        if ($process_result->exitCode() !== 0) {
            if (! $ignore_errors) {
                // Check if deployment was cancelled while command was running
                if (isset($this->application_deployment_queue)) {
                    $this->application_deployment_queue->refresh();
                    if ($this->application_deployment_queue->status === ApplicationDeploymentStatus::CANCELLED_BY_USER->value) {
                        throw new \RuntimeException('Deployment cancelled by user', 69420);
                    }
                }

                // Don't immediately set to FAILED - let the retry logic handle it
                // This prevents premature status changes during retryable SSH errors
                $error = $process_result->errorOutput();
                if (empty($error)) {
                    $error = $process_result->output() ?: 'Command failed with no error output';
                }
                $redactedCommand = $this->redact_sensitive_info($command);
                throw new DeploymentException("Command execution failed (exit code {$process_result->exitCode()}): {$redactedCommand}\nError: {$error}");
            }
        }
    }

    /**
     * Add a log entry for SSH retry attempts
     */
    private function addRetryLogEntry(int $attempt, int $maxRetries, int $delay, string $errorMessage)
    {
        $retryMessage = "SSH connection failed. Retrying... (Attempt {$attempt}/{$maxRetries}, waiting {$delay}s)\nError: {$errorMessage}";

        $new_log_entry = [
            'output' => $this->redact_sensitive_info($retryMessage),
            'type' => 'stdout',
            'timestamp' => Carbon::now('UTC'),
            'hidden' => false,
            'batch' => static::$batch_counter,
        ];

View on GitHub (pinned to 70b9acc424)

Solutions

  1. Open the deployment logs and read the 'Error:' section under the failing command — it is the command's stderr and names the root cause.
  2. SSH into the destination server and re-run the redacted command shown in the message to reproduce the failure interactively.
  3. Check server health: df -h for disk space, docker ps to confirm the daemon, and curl to the registry from the server.
  4. For git failures, verify the branch/tag exists and that the deploy key/token still has access to the repository.
  5. Fix the underlying cause (Dockerfile, build pack command, env vars) and redeploy; transient SSH errors are retried automatically by the SSH retry logic before this exception surfaces.

Example fix

// before: deployment fails with
// Command execution failed (exit code 1): git clone -b $branch ... 
// Error: Remote branch main not found in upstream origin
// after: point the application at a branch that exists, then redeploy
$application->update(['git_branch' => 'master']);
$application->deploy();
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight the destination server before triggering a deployment
use App\Models\Server;
$server = Server::findOrFail($destination->server_id);
instant_remote_process(['docker info >/dev/null && df -h / | tail -1'], $server);
// throws early with a clearer error than a mid-deploy failure

Try / catch

try {
    $application->deploy();
} catch (\App\Exceptions\DeploymentException $e) {
    // message contains exit code, redacted command, and stderr
    report($e);
    // mark the attempt failed in your tracker; keep deployment logs for triage
}

Prevention

When it happens

Trigger: Any deployment command that exits non-zero: git clone/pull failing on a missing branch, missing deploy key or expired token; docker build failing on a bad Dockerfile or unpullable base image; docker compose up failing; a run command in the build pack exiting non-zero; the destination server having a full disk or a stopped Docker daemon.

Common situations: Private repo without a working deploy key; typo'd branch/tag or image tag; missing build arg or environment variable used during build; registry rate limits or network problems on the server; disk exhausted so layers cannot be written; server Docker daemon down while SSH itself still works.

Related errors


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