coollabsio/coolify · error · DeploymentException

Post-deployment command: Could not find a valid container. I

Error message

Post-deployment command: Could not find a valid container. Is the container name correct?

What it means

Same container-resolution logic as the pre-deployment variant, but thrown by run_post_deployment_command() after the new release is up. Because the check runs against freshly started containers, a post-deployment command fails when the app runs multiple containers and post_deployment_command_container is missing or no longer prefix-matches '{name}-{application-uuid}' of the running set.

Source

Thrown at app/Jobs/ApplicationDeploymentJob.php:4807

    private function run_post_deployment_command()
    {
        if (empty($this->application->post_deployment_command)) {
            return;
        }
        $this->application_deployment_queue->addLogEntry('----------------------------------------');
        $this->application_deployment_queue->addLogEntry('Executing post-deployment command (see debug log for output).');

        $containers = getCurrentApplicationContainerStatus($this->server, $this->application->id, $this->pull_request_id);
        if ($containers->count() == 0) {
            $this->application_deployment_queue->addLogEntry('Post-deployment command: No running containers found. Skipping.');

            return;
        }

        $container = $this->resolveCommandContainer($containers, $this->application->post_deployment_command_container, 'Post-deployment');
        if ($container === null) {
            throw new DeploymentException('Post-deployment command: Could not find a valid container. Is the container name correct?');
        }

        $containerName = data_get($container, 'Names');
        if ($containerName) {
            $this->validateContainerName($containerName);
        }
        // Security: post_deployment_command is intentionally treated as arbitrary shell input.
        // See the equivalent comment in run_pre_deployment_command() for the full security rationale.
        // Newlines are normalized to spaces to prevent injection via SSH heredoc transport.
        $postCommand = str_replace(["\r\n", "\r", "\n"], ' ', $this->application->post_deployment_command);
        $cmd = "sh -c '".str_replace("'", "'\''", $postCommand)."'";
        $exec = "docker exec {$containerName} {$cmd}";
        try {
            $this->execute_remote_command(
                [
                    'command' => $exec,
                    'hidden' => true,
                    'save' => 'post-deployment-command-output',

View on GitHub (pinned to 70b9acc424)

Solutions

  1. Set 'Post-deployment command container' in the application's deployment command settings to the bare service name (e.g. 'app'), not the full container name.
  2. Check the debug log 'Available: ...' line to see which running containers the command could target and pick one.
  3. Confirm the container survives the rollout — if the service is renamed in the new compose, update the field to the new name.
  4. docker ps on the destination server to confirm the container is actually running for this application.

Example fix

// before: multi-container app, no target chosen
$application->post_deployment_command = 'php artisan optimize:clear';
$application->post_deployment_command_container = null;

// after
$application->post_deployment_command = 'php artisan optimize:clear';
$application->post_deployment_command_container = 'app';
$application->save();
Defensive patterns

Strategy: validation

Validate before calling

// Before saving a post-deployment command, check it against current containers
$containers = getCurrentApplicationContainerStatus($server, $application->id, $pullRequestId);
if ($containers->count() > 1) {
    $prefix = ($application->post_deployment_command_container ?? '') . '-' . $application->uuid;
    if (! $containers->pluck('Names')->contains(fn ($n) => str_starts_with($n, $prefix))) {
        // block save: choose a container name from the running set
    }
}

Try / catch

catch (DeploymentException $e) { if (str_starts_with($e->getMessage(), 'Post-deployment command:')) { mark deployment as config error, show 'Available:' list from logs, no auto-retry; } else { throw $e; } }

Prevention

When it happens

Trigger: Multi-container app (scaled replicas, multiple compose services) with post_deployment_command_container empty; the configured container name matches a compose service that was renamed or removed in the new release; the target container crashed immediately after starting, so it is absent from getCurrentApplicationContainerStatus.

Common situations: Renaming compose services in the same commit that the post-deployment command was expected to run in; scaling to 2+ replicas after the command was configured; container name entered with the full '-uuid' suffix; PR deploy where the PR-suffixed container is expected but missing.

Related errors


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