For awsvpc-mode task definitions, networkConfiguration.awsvpcConfiguration is required and must list subnets and securityGroups; assignPublicIp (ENABLED/DISABLED, default DISABLED) controls whether the task's ENI gets a public IP.
Pin a Fargate platform version with --platform-version (e.g. 1.4.0 or LATEST); if omitted, ECS uses the latest revision of the platform version.
Apply per-run overrides with --overrides, e.g. '{"containerOverrides":[{"name":"my-container","command":["python","job.py"],"environment":[{"name":"ENV","value":"prod"}]}]}' to change command/env/cpu/memory without a new task definition revision.
Tag the run with --tags key=Job,value=nightly-etl and --propagate-tags TASK_DEFINITION if you want task-definition tags copied onto the task.
Capture the task ARN from the RunTask response (tasks[0].taskArn).
Block until it finishes: aws ecs wait tasks-stopped --cluster my-cluster --tasks <taskArn> (polls DescribeTasks every 6 seconds, up to 100 attempts, ~10 minutes before failing with exit code 255).
Read the outcome: aws ecs describe-tasks --cluster my-cluster --tasks <taskArn> --query 'tasks[0].containers[].{name:name,exitCode:exitCode,reason:reason}' — exitCode 0 means success; a populated reason with a null exitCode usually means the container never started or was killed.
Also check tasks[0].stopCode and tasks[0].stoppedReason at the task level for infrastructure-level failures distinct from the container's own exitCode.
Official docs: https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_RunTask.html | https://docs.aws.amazon.com/cli/latest/reference/ecs/wait/tasks-stopped.html | https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_Container.html | https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_cannot_pull_image.html
Known gotchas
launchType and capacityProviderStrategy are mutually exclusive on RunTask — supplying both raises a parameter error.
assignPublicIp defaults to DISABLED; if the task is in a private subnet with no NAT gateway (or you forget to enable it in a public subnet), the agent can't reach ECR/CloudWatch and you get CannotPullContainerError or ResourceInitializationError.
aws ecs wait tasks-stopped times out after 100 attempts at 6-second intervals (~10 minutes) and returns exit code 255 if the task is still running — a client-side timeout, not a task failure.
exitCode can be null even for a task that ran, if the essential container was OOM-killed or stopped externally (StopTask, capacity reclamation) — always read reason/stoppedReason alongside exitCode.
Reusing the same --client-token with different parameters on a retried RunTask call returns a ConflictException rather than silently succeeding.
RunTask/DescribeTasks results are eventually consistent; AWS recommends polling DescribeTasks with exponential backoff rather than assuming immediate consistency after RunTask returns.
If revision isn't specified in --task-definition, ECS resolves to the latest ACTIVE revision at request time — pin an explicit revision for reproducible one-off jobs.
Managed-scaling capacity providers can throw ClientException when the PROVISIONING tasks quota is reached — retry with backoff rather than hammering RunTask.
Give your agent this knowledge — and 16,300+ more routes
One MCP install gives any agent live access to the full route map across 5,800+ domains, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp
Need this verified for your stack — or a route we don't have yet?