Skip to main content
Tasks from your new version started, but a health check never reported healthy, so ECS stopped them and the rollout failed. The failure came from the application’s code or configuration. Two different checks produce this code. Read the provider reason first, because the fix differs for each.

Which health check failed

Fjall emits no container health check unless you declare one. A service with no healthCheck block can only have failed the ALB check. Every service with a container port in a cluster that has an ALB, the default, registers with a target group, so the target-group check runs on every rollout whether or not you configured a path for it. A cluster set to loadBalancer: false or directAccess: true has no ALB and creates no target group, so only the container check can fail there.

Target-group defaults Fjall sets

Fjall sets no success matcher, so the health-check path must answer HTTP 200. Only the path is configurable in infrastructure.ts. The interval, thresholds and grace period are fixed by the construct.

Why this happens

ALB target-group check
  • The path returns a non-200 status. The default path is /, so a service that only serves /api returns 404 on every probe.
  • The application binds a different port from the port declared on the container.
  • The application binds 127.0.0.1 instead of 0.0.0.0, so the load balancer cannot reach it.
  • The first response takes longer than the 120-second grace period, usually because the health route waits on a database pool or a cache warm.
Container health check
  • The command probes a route the application does not serve.
  • startPeriod is shorter than the boot, so ECS counts the early failures against the task.
  • The probe binary is missing from the image. A slim base image often ships without curl or wget.
The deployment failure sits in the ecs_stabilise phase. The provider reason from ECS may include the stopCode for the failed tasks.

How to fix it

  1. Read the provider reason and pick the branch from the table above.
  2. ALB branch. Point routing.healthCheckPath at a route the service serves and returns 200 for, then confirm the container port matches the port the process binds.
    infrastructure.ts
  3. Container branch. Check the command and startPeriod, and confirm the probe binary exists in the image.
    infrastructure.ts
  4. Test the check locally. Run the image, wait for it to boot, then probe the same path from outside the container. It should return 200 within the interval.
  5. For a slow boot, serve the health route before the expensive warm-up rather than after it. The ALB grace period is fixed at 120 seconds, so a health route gated behind cache warming cannot be rescued by configuration. On the container check, raise startPeriod instead.
  6. Deploy again once the check passes locally.
Container health-check bounds: interval 5 to 300 seconds, timeout 2 to 60, retries 1 to 10, startPeriod 0 to 300. Values outside those ranges fail validation before the deploy starts.

What Fjall shows you

The deployment’s detail page on fjall.io shows the failure title, this code, the per-deployment detail, the ECS reason verbatim under “ECS said”, the remediation steps, and a link back to this page. The Steps timeline ends with the latest ECS event message once every step has completed. The deployments list carries the failure title on the deployment’s row. Non-interactive CLI runs print the same fields in an Error Detail block.

Next Steps

ECS cluster

Configure containers, ports, routing and health-check paths.

Deployment safety

How the circuit breaker and the ECS event tail protect your rollouts.

ecs.circuit_breaker

The neighbouring code for tasks that never started at all.

fjall releases

Check what is currently running after a failed rollout.