{"record":{"id":"5be9362660fbb933","repo":"coollabsio/coolify","slug":"private-key-not-found-please-add-a-private-key-to","errorCode":null,"errorMessage":"Private key not found. Please add a private key to the application and try again.","messagePattern":"Private key not found\\. Please add a private key to the application and try again\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"app/Models/Application.php","lineNumber":1598,"sourceCode":"                if ($exec_in_docker) {\n                    $commands->push($this->gitCommand(executeInDocker($deployment_uuid, $base_command)));\n                } else {\n                    $commands->push($this->gitCommand($base_command));\n                }\n\n                return [\n                    'commands' => $this->gitCommandsAsShellCommand($commands),\n                    'branch' => $branch,\n                    'fullRepoUrl' => $fullRepoUrl,\n                ];\n            }\n        }\n\n        if ($this->deploymentType() === 'deploy_key') {\n            $fullRepoUrl = $customRepository;\n            $private_key = data_get($this, 'private_key.private_key');\n            if (is_null($private_key)) {\n                throw new RuntimeException('Private key not found. Please add a private key to the application and try again.');\n            }\n            $private_key = base64_encode($private_key);\n            // When used with executeInDocker (which uses bash -c '...'), we need to escape for bash context\n            // Replace ' with '\\'' to safely escape within single-quoted bash strings\n            $escapedCustomRepository = str_replace(\"'\", \"'\\\\''\", $customRepository);\n            $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}'\";\n\n            $commands = $this->gitSshKeySetupCommands($deployment_uuid, $private_key, $exec_in_docker);\n\n            if ($exec_in_docker) {\n                $commands->push($this->gitCommand(executeInDocker($deployment_uuid, $base_command)));\n            } else {\n                $commands->push($this->gitCommand($base_command));\n            }\n\n            return [\n                'commands' => $commands,\n                'branch' => $branch,","sourceCodeStart":1580,"sourceCodeEnd":1616,"githubUrl":"https://github.com/coollabsio/coolify/blob/70b9acc42467278373e00de77abb40684e25b395/app/Models/Application.php#L1580-L1616","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Open the application's Git source settings and select an existing private key (or create one) under the deploy key section.","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.","If you don't need key-based auth, switch the application to GitHub App / OAuth token authentication instead."],"exampleFix":"// before: deploy_key selected, relation empty\n$application->private_key_id = null;\n\n// after\n$application->private_key_id = $privateKey->id;\n$application->save();","handlingStrategy":"validation","validationCode":"// Guard before generating import commands / deploying\nif ($application->deploymentType() === 'deploy_key'\n    && blank(data_get($application, 'private_key.private_key'))) {\n    throw new InvalidArgumentException('Attach a private key before deploying with a deploy key.');\n}","typeGuard":"function hasUsableDeployKey(Application $app): bool\n{\n    return $app->deploymentType() === 'deploy_key'\n        && $app->private_key()->exists()\n        && filled(data_get($app, 'private_key.private_key'));\n}","tryCatchPattern":"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; } }","preventionTips":["Enforce at save time: applications with source deploy_key must have private_key_id set.","Refuse to delete PrivateKeys still referenced by applications (or warn loudly).","Include a deploy-key presence check in pre-deploy validation checks."],"tags":["git","deploy-key","ssh","coolify"],"backgroundTag":"missing-deploy-key","analyzedSha":"70b9acc42467278373e00de77abb40684e25b395","analyzedAt":"2026-08-17T01:41:01.313Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}