# How to debug Terraform errors

Source: https://docs.quake.ai/docs/automation/how-to/terraform-error-handling
Markdown: https://docs.quake.ai/docs/automation/how-to/terraform-error-handling.md

---

# How to debug Terraform errors

Terraform errors fall into distinct categories that require different debugging approaches: configuration errors caught before any API call, provider errors from the OpenStack API, and state management issues. This guide covers the debugging workflow, common error patterns, and recovery procedures.

## Debug output

Enable verbose logging to see the full HTTP request/response cycle between Terraform and the OpenStack API.

### Set the log level

```bash
export TF_LOG=DEBUG
terraform apply
```

| Level | Output |
|---|---|
| `TRACE` | Maximum detail including provider internals |
| `DEBUG` | HTTP requests, responses, and provider logic |
| `INFO` | High-level operation flow |
| `WARN` | Warnings only |
| `ERROR` | Errors only |

### Write logs to a file

```bash
export TF_LOG=DEBUG
export TF_LOG_PATH=./terraform-debug.log
terraform apply
```

Review the log for the HTTP status code and response body from the OpenStack API. Search for `HTTP/1.1 4` or `HTTP/1.1 5` to find error responses.

### Disable logging

```bash
unset TF_LOG
unset TF_LOG_PATH
```

## Debugging workflow

Follow this sequence when a Terraform operation fails.

### 1. Format and validate

Catch syntax and configuration errors before they reach the API:

```bash
terraform fmt -check -recursive
terraform validate
```

`validate` checks HCL syntax, required attributes, and type constraints. It does not contact the OpenStack API.

### 2. Plan

```bash
terraform plan -out=tfplan
```

Review the plan output for unexpected resource changes. If the plan itself fails, the error is an authentication failure (`Authentication failed` or `Could not find Application Credential`) or a provider-configuration failure (`No suitable endpoint could be found in the service catalog`).

### 3. Apply with targeted debugging

If `apply` fails on a specific resource, isolate it:

```bash
terraform apply -target=openstack_compute_instance_v2.web
```

Enable debug logging for the isolated apply to capture the exact API interaction.

### 4. Inspect state

After a partial failure, check what Terraform recorded:

```bash
terraform state list
terraform state show openstack_compute_instance_v2.web
```

## Common OpenStack provider errors

| Error message | Cause | Fix |
|---|---|---|
| `Error: Error creating OpenStack image client: Authentication failed` (wrong `OS_APPLICATION_CREDENTIAL_SECRET`) or `Error: ... Could not find Application Credential: <id>` (HTTP 404, wrong or deleted `OS_APPLICATION_CREDENTIAL_ID`) | The app credential secret is wrong, the credential ID is wrong, the credential was deleted, or the credential is scoped to a different project | Verify `OS_AUTH_URL` and the app-credential set (`OS_AUTH_TYPE=v3applicationcredential`, `OS_APPLICATION_CREDENTIAL_ID`, `OS_APPLICATION_CREDENTIAL_SECRET`). Re-source your `openrc.sh` from the [generated openrc.sh](/docs/tools/generate-app-credentials). |
| `Error: Error creating OpenStack image client: No suitable endpoint could be found in the service catalog.` | The configured `OS_REGION_NAME` does not exist in the service catalog, or the service is not enabled in that region | Set `OS_REGION_NAME` to a region that appears in `openstack catalog list` (for example, `us-east-1`). |
| `Error: Error creating openstack_networking_floatingip_v2: Expected HTTP response code [201 202] when accessing [POST .../v2.0/floatingips], but got 409 instead {"NeutronError": {"type": "OverQuota", "message": "Quota exceeded for resources: ['public_ip']."}}` | Project floating-IP quota is exhausted | Check quota: `openstack quota show --usage`. Release unused floating IPs (`openstack floating ip delete`) or request a quota increase. |
| `Error: Your query returned no results. Please change your search criteria and try again.` | A data source (network, image, flavor) name does not match any resource in the project | Run `openstack network list`, `openstack image list`, `openstack flavor list` to verify the exact name, and confirm the data source's filters (for example, `most_recent = true` on Glance images). |
| `"Quota exceeded"` (403 or 413) | Project quota is full | Free resources or request a quota increase. See [quota troubleshooting](/docs/operate/troubleshooting/quota-and-limits). |
| `"Conflict"` (409) | Resource is in a transitional state | Wait and retry. The resource may be building, attaching, or being modified by another operation. |
| `"Unauthorized"` (401) | Token expired during a long apply | Tokens have a limited lifetime. For long operations, use application credentials instead of token-based auth. |
| `Error: ... Build of instance ... aborted: Failed to allocate the network(s), not rescheduling.` | The Compute API cannot auto-allocate a port on an external network (for example, `PublicStatic`) | Attach to `PublicEphemeral` for direct attach, or for `PublicStatic` declare an explicit `openstack_networking_port_v2` and pair it with `openstack_networking_floatingip_v2` + `openstack_networking_floatingip_associate_v2` (see the [Simple VM template](/resources/iac-templates/simple-vm)). |



Many garbled or unhelpful Terraform error messages originate from the `gophercloud` Go SDK's error formatting. Enable `TF_LOG=DEBUG` to see the actual HTTP response body from the API, which contains the real error message.



## State lock recovery

Terraform uses a lock to prevent concurrent modifications. If a Terraform process crashes or is interrupted, the lock may remain.

### Symptoms

```text
Error: Error acquiring the state lock
Lock Info:
  ID:        12345678-abcd-...
  Path:      terraform.tfstate
  Operation: OperationTypeApply
  Who:       user@hostname
  Created:   2026-04-08 12:00:00 +0000 UTC
```

### Resolution

1. Verify no other Terraform process is running against the same state.
2. Force-unlock using the lock ID from the error message:

```bash
terraform force-unlock 12345678-abcd-...
```



Only force-unlock if you are certain no other process is using the state. Unlocking while another apply is running can corrupt state.



## Plan/apply drift

Drift occurs when resources are modified outside Terraform (via the console, CLI, or another automation tool).

### Detecting drift

```bash
terraform plan
```

If the plan shows changes you did not make in your `.tf` files, resources have drifted. Terraform will report either an update-in-place or a forced replacement.

### Resolving drift

**Option 1: Accept the external changes.** Refresh state to match reality:

```bash
terraform apply -refresh-only
```

Review the changes and approve. This updates Terraform's state without modifying infrastructure.

**Option 2: Revert to Terraform's definition.** Run a normal apply to push the `.tf` configuration back to the infrastructure:

```bash
terraform apply
```

## Import errors

When importing existing resources into Terraform state:

```bash
terraform import openstack_compute_instance_v2.web INSTANCE_ID
```

### Common import failures

| Error | Cause | Fix |
|---|---|---|
| `Cannot import non-existent remote object` | The resource ID is wrong or the resource was deleted | Verify with `openstack server show INSTANCE_ID` |
| `Resource already managed by Terraform` | The resource is already in state | Check with `terraform state list`. Remove the duplicate with `terraform state rm` if appropriate. |
| Post-import plan shows changes | The `.tf` definition does not match the imported resource's actual configuration | Update the `.tf` file to match the real resource, then run `terraform plan` until it shows no changes. |

## Provider-level retry configuration

The OpenStack Terraform provider supports retry configuration for transient failures:

```hcl
provider "openstack" {
  max_retries = 3
}
```

This retries on connection errors and 5xx responses. For more granular control over retry behavior, see [Retry and resilience patterns](/reference/api-conventions/retry-and-resilience).

## See also

- [How to deploy infrastructure with Terraform](/docs/automation/how-to/terraform-simple): basic Terraform workflow
- [Full-stack Terraform deployment](/docs/automation/how-to/terraform-full-stack): multi-resource deployment
- [Terraform state management](/docs/automation/how-to/state-management): remote state and locking
- [Automation API error reference](/reference/automation/api-errors): Heat API status codes and stack state machine
- [Error response format](/reference/api-conventions/error-response-format): parsing OpenStack JSON errors
- [Auth token diagnostics](/docs/operate/troubleshooting/auth-token-diagnostics): credential and token debugging
- [Retry and resilience patterns](/reference/api-conventions/retry-and-resilience): backoff algorithms and retry guidance
