{"record":{"id":"39d0b863c34f11a2","repo":"coollabsio/coolify","slug":"pre-deployment-command-could-not-find-a-valid-con","errorCode":null,"errorMessage":"Pre-deployment command: Could not find a valid container. Is the container name correct?","messagePattern":"Pre-deployment command: Could not find a valid container\\. Is the container name correct\\?","errorType":"exception","errorClass":"DeploymentException","httpStatus":null,"severity":"error","filePath":"app/Jobs/ApplicationDeploymentJob.php","lineNumber":4763,"sourceCode":"        return null;\n    }\n\n    private function run_pre_deployment_command()\n    {\n        if (empty($this->application->pre_deployment_command)) {\n            return;\n        }\n        $containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id);\n        if ($containers->count() == 0) {\n            $this->application_deployment_queue->addLogEntry('Pre-deployment command: No running containers found. Skipping.');\n\n            return;\n        }\n        $this->application_deployment_queue->addLogEntry('Executing pre-deployment command (see debug log for output/errors).');\n\n        $container = $this->resolveCommandContainer($containers, $this->application->pre_deployment_command_container, 'Pre-deployment');\n        if ($container === null) {\n            throw new DeploymentException('Pre-deployment command: Could not find a valid container. Is the container name correct?');\n        }\n\n        $containerName = data_get($container, 'Names');\n        if ($containerName) {\n            $this->validateContainerName($containerName);\n        }\n        // Security: pre_deployment_command is intentionally treated as arbitrary shell input.\n        // Users (team members with deployment access) need full shell flexibility to run commands\n        // like \"php artisan migrate\", \"npm run build\", etc. inside their own application containers.\n        // The trust boundary is at the application/team ownership level — only authenticated team\n        // members can set these commands, and execution is scoped to the application's own container.\n        // The single-quote escaping here prevents breaking out of the sh -c wrapper, but does not\n        // restrict the command itself. Container names are validated separately via validateContainerName().\n        // Newlines are normalized to spaces to prevent injection via SSH heredoc transport\n        // (matches the pattern used for health_check_command at line ~2824).\n        $preCommand = str_replace([\"\\r\\n\", \"\\r\", \"\\n\"], ' ', $this->application->pre_deployment_command);\n        $cmd = \"sh -c '\".str_replace(\"'\", \"'\\''\", $preCommand).\"'\";\n        $exec = \"docker exec {$containerName} {$cmd}\";","sourceCodeStart":4745,"sourceCodeEnd":4781,"githubUrl":"https://github.com/coollabsio/coolify/blob/70b9acc42467278373e00de77abb40684e25b395/app/Jobs/ApplicationDeploymentJob.php#L4745-L4781","documentation":"Coolify throws this DeploymentException from run_pre_deployment_command() when a pre-deployment command is configured but resolveCommandContainer() cannot pick a container to run it in. Single-container apps always use their one running container; multi-container apps must have pre_deployment_command_container set, and it must prefix-match a running container named '{name}-{application-uuid}'. The job log right before the throw lists the containers that were actually available.","triggerScenarios":"Application has 2+ running containers (scaling, extra compose services, sidecars) and pre_deployment_command_container is empty — resolveCommandContainer logs 'Multiple containers found but no container name specified' and returns null; or the configured name does not prefix-match any running container ('Container X not found. Available: ...'); or the target container exited/crashed before this step, since getCurrentApplicationContainerStatus only returns running containers for this application id and pull_request_id.","commonSituations":"Scaling an app or adding a sidecar service to docker-compose and leaving the container field blank; renaming the compose service after configuring the command so the old name no longer exists; entering the full container name including the -uuid suffix instead of just the service name; PR deployments where the matching PR container does not exist.","solutions":["Open the application's deployment command settings and set 'Pre-deployment command container' to the service name of exactly one container, without the -uuid suffix (e.g. 'app').","Read the deployment debug log line 'Available: ...' — it lists the exact running container names Coolify sees; copy the prefix before the -uuid part.","Verify on the server with docker ps that the intended container is running and belongs to the same application (and pull request) being deployed.","If the container list is stale or contains leftovers from old deploys, remove the orphaned containers or redeploy so status is refreshed."],"exampleFix":"// before: command set, container never selected for a multi-container app\n$application->pre_deployment_command = 'php artisan migrate';\n$application->pre_deployment_command_container = null;\n\n// after: pin the command to one service name (job appends '-{uuid}' itself)\n$application->pre_deployment_command = 'php artisan migrate';\n$application->pre_deployment_command_container = 'app';\n$application->save();","handlingStrategy":"validation","validationCode":"// Before enabling/saving a pre-deployment command, confirm the target resolves\n$containers = getCurrentApplicationContainerStatus($server, $application->id, $pullRequestId);\n$names = $containers->pluck('Names');\nif ($containers->count() === 0) {\n    // no running containers: command will be skipped, not thrown — decide if acceptable\n}\nif ($containers->count() > 1) {\n    $prefix = ($application->pre_deployment_command_container ?? '') . '-' . $application->uuid;\n    if (blank($application->pre_deployment_command_container)\n        || ! $names->contains(fn ($n) => str_starts_with($n, $prefix))) {\n        // block: 'set pre_deployment_command_container to one of: ' . $names->implode(', ')\n    }\n}","typeGuard":null,"tryCatchPattern":"catch (DeploymentException $e) { if (str_starts_with($e->getMessage(), 'Pre-deployment command:')) { surface as configuration error with the logged 'Available:' container list; do not retry; } else { throw $e; } }","preventionTips":["Whenever the app has or may have multiple containers, always set the command container field to a stable service name (no -uuid suffix).","Keep compose service names stable across releases; if renamed, update pre/post deployment command container fields in the same change.","After deployment failures, read the 'Available: ...' debug log line — it is the exact match set."],"tags":["docker","deployment","container-resolution","coolify"],"backgroundTag":"container-not-found","analyzedSha":"70b9acc42467278373e00de77abb40684e25b395","analyzedAt":"2026-08-17T01:41:01.313Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}