coollabsio/coolify · error · RuntimeException

Private key not found. Please add a private key to the appli

Error message

Private key not found. Please add a private key to the application and try again.

What it means

On the deploy_key path of Application::generateGitImportCommands(), Coolify reads the attached private key via data_get($this, 'private_key.private_key'). When the private_key relation resolves to nothing — private_key_id is null or the PrivateKey row was deleted — the clone command cannot be built, so it throws RuntimeException before any Git command runs.

Source

Thrown at app/Models/Application.php:1598

                if ($exec_in_docker) {
                    $commands->push($this->gitCommand(executeInDocker($deployment_uuid, $base_command)));
                } else {
                    $commands->push($this->gitCommand($base_command));
                }

                return [
                    'commands' => $this->gitCommandsAsShellCommand($commands),
                    'branch' => $branch,
                    'fullRepoUrl' => $fullRepoUrl,
                ];
            }
        }

        if ($this->deploymentType() === 'deploy_key') {
            $fullRepoUrl = $customRepository;
            $private_key = data_get($this, 'private_key.private_key');
            if (is_null($private_key)) {
                throw new RuntimeException('Private key not found. Please add a private key to the application and try again.');
            }
            $private_key = base64_encode($private_key);
            // When used with executeInDocker (which uses bash -c '...'), we need to escape for bash context
            // Replace ' with '\'' to safely escape within single-quoted bash strings
            $escapedCustomRepository = str_replace("'", "'\\''", $customRepository);
            $base_command = "GIT_SSH_COMMAND=\"ssh -o ConnectTimeout=30 -p {$customPort} -o Port={$customPort} -o LogLevel=ERROR -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -i {$customSshKeyLocation} -o IdentitiesOnly=yes\" {$base_command} '{$escapedCustomRepository}'";

            $commands = $this->gitSshKeySetupCommands($deployment_uuid, $private_key, $exec_in_docker);

            if ($exec_in_docker) {
                $commands->push($this->gitCommand(executeInDocker($deployment_uuid, $base_command)));
            } else {
                $commands->push($this->gitCommand($base_command));
            }

            return [
                'commands' => $commands,
                'branch' => $branch,

View on GitHub (pinned to 70b9acc424)

Solutions

  1. Open the application's Git source settings and select an existing private key (or create one) under the deploy key section.
  2. If the key was deleted, recreate it in Keys, add its public half to the repository as a (read-only) deploy key, then attach it to the application.
  3. If you don't need key-based auth, switch the application to GitHub App / OAuth token authentication instead.

Example fix

// before: deploy_key selected, relation empty
$application->private_key_id = null;

// after
$application->private_key_id = $privateKey->id;
$application->save();
Defensive patterns

Strategy: validation

Validate before calling

// Guard before generating import commands / deploying
if ($application->deploymentType() === 'deploy_key'
    && blank(data_get($application, 'private_key.private_key'))) {
    throw new InvalidArgumentException('Attach a private key before deploying with a deploy key.');
}

Type guard

function hasUsableDeployKey(Application $app): bool
{
    return $app->deploymentType() === 'deploy_key'
        && $app->private_key()->exists()
        && filled(data_get($app, 'private_key.private_key'));
}

Try / catch

catch (RuntimeException $e) { if (str_contains($e->getMessage(), 'Private key not found')) { redirect to Git source settings with instructions to attach a key; } else { throw $e; } }

Prevention

When it happens

Trigger: Application's source uses deploymentType() 'deploy_key' but no private key is attached; the key record was deleted from Keys while apps still referenced it; app imported/restored without carrying private_key_id.

Common situations: Deleting a shared private key after moving to another auth method while one application still points at it; switching an application's authentication type and forgetting to attach a key; team member cleanup of Keys & Tokens.

Related errors


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