Skip to content
Back to skills

003 Name Skill 1a74484d

ASecurity

Terraform debugging for small teams. Diagnoses plan/apply failures, state issues, and Azure provider errors. Use when asked to "fix terraform", "debug infra", "why did apply fail", or "/tfappfix".

  • 9 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 11, 2026
devopsbashazureterraformdebugginggitapibackendsecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned October 11, 2026

npx -y skills add tools-only/X-Skills --skill 003-name-skill_1a74484d --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of 003 Name Skill 1a74484d?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for 003 Name Skill 1a74484d
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/tools-only-003-name-skill-1a74484d/badge)](https://www.skillsdirectory.com/skills/tools-only-003-name-skill-1a74484d)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

SKILL.md
---
name: tfappfix
description: Terraform debugging for small teams. Diagnoses plan/apply failures, state issues, and Azure provider errors. Use when asked to "fix terraform", "debug infra", "why did apply fail", or "/tfappfix".
---

# Terraform Debugging (/tfappfix)

Pragmatic terraform debugging for a 2-person team. No enterprise overhead.

## Philosophy: What This Skill Is NOT

**Skip these enterprise patterns - you are 2 people:**
- Complex policy checks (Sentinel/OPA) - just review the plan
- Multi-workspace orchestration - you have dev/prod, that is enough
- Drift detection dashboards - just run `terraform plan`
- Checkpoint files - terraform state IS the checkpoint
- 4-agent planning - talk to each other instead

**Terraform already provides:**
- State management (do not reinvent it)
- Change detection (`plan -detailed-exitcode`)
- Locking (do not build another layer)
- Dependency resolution

**This skill focuses on:**
- Diagnosing why plan/apply failed
- Common Azure provider issues
- Safe state manipulation when needed
- Getting CI green again

## Triggers

- `/tfappfix`, "fix terraform", "debug infra", "why did apply fail"
- "plan is failing", "state is locked", "terraform error"

## The 80/20 of Terraform Debugging

| Frequency | Problem Type | Solution |
|-----------|--------------|----------|
| 80% | Code/config error | Read error, fix code, push, CI applies |
| 15% | State issues | Unlock, rm, import (with user confirmation) |
| 5% | Azure API / provider | Wait, retry, or workaround |

**Most terraform issues are solved by reading the error message carefully.**

## Workflow

```
Phase 0: CONTEXT
  - Identify the failing stack
  - Get the error (from user, CI logs, or local run)

Phase 1: DIAGNOSE
  - Run fmt, validate, plan locally
  - Check state lock status if relevant
  - Check Azure resource status if apply failed

Phase 2: FIX
  - Apply code changes
  - State ops require user confirmation

Phase 3: VERIFY
  - Plan shows expected changes
  - Push to trigger CI
```

### Phase 0: Get Context

**Find out:**
1. Which stack? (Look for directories with `main.tf` or `*.tf` files)
2. What is the error? (CI log, local error, or symptom)
3. Plan or apply failure?

**If user provides a GitHub Actions run URL:**
```bash
gh run view <run-id> --log-failed
```

### Phase 1: Diagnose

**Always start here - run the basics:**

```bash
cd <stack-path>  # directory containing main.tf

# 1. Format check
terraform fmt -check -recursive

# 2. Validate (fast, no backend)
terraform init -backend=false
terraform validate

# 3. Full plan (if validate passes)
terraform init
terraform plan -out=debug.tfplan
```

**Check state lock (if plan hangs):**
For Azure Blob backend, check lease status with `az storage blob show`.

**Check Azure resource status (if apply failed mid-way):**
```bash
az resource list -g <resource-group> --query "[].{name:name, state:properties.provisioningState}" -o table
```

### Phase 2: Fix

#### Error: State Lock

For Azure Blob backend:
```bash
# Check lease status
az storage blob show --container-name <container> --name <state-file> --account-name <storage> --query "properties.lease"

# Break lease (ASK USER FIRST)
az storage blob lease break --container-name <container> --name <state-file> --account-name <storage>
```

**Safety gate:** Always ask user before breaking a lock.

#### Error: Resource Already Exists

Resource exists in Azure but not in state.

**⚠️ CRITICAL: 99% of cases should DELETE, not import.**

**DEFAULT ACTION (do not ask, just do this):**
1. Ask user to DELETE the resource in Azure Portal or CLI
2. Re-run terraform to create it fresh under Terraform management

```bash
# Example: delete a role assignment
az role assignment delete --ids "<resource-id>"

# Example: delete a generic resource
az resource delete --ids "<resource-id>"
```

**IMPORT IS ALMOST NEVER CORRECT.** Only consider import when ALL of these are true:
1. The resource has existed for a **long time** (months/years, not hours/days)
2. The resource contains **irreplaceable data** or **configuration that cannot be recreated**
3. The resource is managed in a **different terraform repo** OR was created manually before IaC

**If you believe import is appropriate, you MUST:**
1. Stop and ask the user with ALL of these details:
   - Why you believe this qualifies as a rare import case
   - What the resource is and how long it has existed
   - The exact import command you would run
   - The risk: import can cause state corruption if the resource config doesn't match
2. Wait for explicit "yes, import it" confirmation
3. Note: `terraform import` is BLOCKED by the command guard - user must run manually

**DO NOT ask about import** for resources created in the last few days. Just delete and recreate.

#### Error: Resource Not Found (Drift)

Resource in state but deleted from Azure:

```bash
# Remove from state - ASK USER FIRST
terraform state rm <resource.address>
```

#### Error: Provider / API Error

| Error | Cause | Fix |
|-------|-------|-----|
| `StatusCode=409` | Resource busy | Wait 5 min, retry |
| `StatusCode=429` | Rate limited | Retry with `-parallelism=1` |
| `StatusCode=404` on apply | Eventual consistency | Wait 2 min, retry |
| `OperationNotAllowed` | Resource in transitional state | Wait and retry |

#### Error: Module/Provider Version

```bash
terraform providers
terraform init -upgrade
```

### Phase 3: Verify

```bash
# Local plan should show expected changes
terraform plan

# Push to trigger CI
git add <files>
git commit -m "fix(terraform): <description>"
git push

# Monitor CI
gh run watch
```

## Finding Stacks

**Discover terraform stacks in your repo:**
```bash
# Find all directories with terraform files
find . -name "*.tf" -type f | xargs dirname | sort -u

# Or look for backend configurations
grep -r "backend" --include="*.tf" -l
```

**Understand dependencies:**
- Check `terraform_remote_state` data sources for cross-stack references
- Check module sources for shared modules
- Apply order: shared/platform stacks first, then application stacks

## Safety Rules

**BLOCKED (cannot run via Claude - user must run manually):**
- `terraform import` — blocked by command guard
- `terraform state rm` — blocked by command guard
- `terraform apply` — blocked by command guard
- `terraform destroy` — blocked by command guard

**Ask user before:**
- Breaking state locks
- Suggesting user run `terraform import` (see "Resource Already Exists" - 99% should DELETE instead)
- Operations on production stacks
- Any `-force` flags

**Proceed without asking:**
- `terraform fmt`
- `terraform validate`
- `terraform plan`
- `terraform init`
- Code changes to .tf files
- Committing and pushing

## Azure Authentication

```bash
# Check auth
az account show

# Login if needed
az login

# Set subscription
az account set -s <subscription-id>
```

For terraform:
```bash
export ARM_SUBSCRIPTION_ID=$(az  account show --query id -o tsv)
export ARM_TENANT_ID=$(az account show --query tenantId -o tsv)
```

## Error Message Decoder

| Error Message | Meaning | Fix |
|---------------|---------|-----|
| "Error acquiring the state lock" | CI crashed or local tf running | Break lease if stale |
| "Resource already exists" | Exists in Azure, not in state | DELETE resource, recreate (import is rare) |
| "Unsupported attribute" | Module output changed | `terraform init -upgrade` |
| "dial tcp: lookup ... no such host" | DNS/network issue | Retry |
| "AuthorizationFailed" | Missing RBAC | Check permissions |
| "QuotaExceeded" | Azure limits | Request increase or change region |

## When to Escalate

**Talk to your teammate (not Claude):**
- Production outage
- Security-related changes
- Billing/cost decisions
- Architectural changes
- Anything you are not sure about

**This skill is for:**
- Getting a failing plan/apply to pass
- Understanding error messages
- Safe state manipulation with confirmation
- Quick fixes, not redesigns

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…