terraform destroy: Usage, Options & Common CI Errors
Tear down everything Terraform manages - carefully.
terraform destroy removes all resources tracked in state. It is the inverse of apply and is most useful for ephemeral environments and PR preview stacks.
What it does
terraform destroy creates a plan that deletes every resource in the current state, then executes it after approval. It respects dependency order, destroying dependents before their dependencies.
Common usage
# Destroy everything in this state (prompts for yes)
terraform destroy
# Non-interactive teardown (ephemeral PR env cleanup)
terraform destroy -auto-approve -var-file=preview.tfvars
# Destroy only one resource (equivalent to terraform apply -destroy -target=...)
terraform destroy -target=aws_instance.webCommon error in CI: dependency violation on delete
Teardown often fails with "Error: deleting ... : DependencyViolation: resource ... has a dependent object" - for example a VPC that still has a manually-attached ENI, or an S3 bucket that is not empty. Fix: remove the external dependent first (empty the bucket, detach the ENI), or set force_destroy = true on resources that support it (e.g. aws_s3_bucket). Re-run destroy; Terraform retries the dependency chain.
Key options
| Option | Purpose |
|---|---|
| -auto-approve | Skip the destroy confirmation |
| -target=ADDR | Destroy only specific resources |
| -var-file=FILE | Variables for the destroy plan |
| -input=false | Never prompt (required in CI) |
Using this in CI
Cloud CLIs behave differently on a runner than on your laptop. They assume no interactive terminal, no cached credentials, and no browser for device-code flows, so the same command that works locally can hang or fail on a runner.
- Authenticate with a short-lived OIDC token rather than a long-lived static key. GitHub Actions can exchange
id-token: writefor cloud credentials with no stored secret. - Always pass the non-interactive flag. Most cloud CLIs will otherwise prompt and hang until the job times out.
- Pin the CLI version. Cloud CLIs change output formats between minor releases, and any script parsing that output will break silently.
- Set the output format explicitly (
--output json) rather than relying on the default, which can differ by version and configuration profile.