Immutable solution version
Diagnosing a clean plan when infrastructure clearly differs
Complete solution
Plan says no changes but you can see the difference in the console. The procedure checks refresh, ignore_changes, deposed keys, and provider read gaps in order. Not the full reference manual.
TL;DR: Plan says no changes but you can see the difference in the console. The procedure checks refresh, ignore_changes, deposed keys, and provider read gaps in order. Refresh was skipped (-refresh=false) so Terraform never looked. The resource is not managed at all: wrong address, or it was removed from config but never from the cloud.
The fix
TL;DR: Plan says no changes but you can see the difference in the console. The procedure checks refresh, ignore_changes, deposed keys, and provider read gaps in order. Refresh was skipped (-refresh=false) so Terraform never looked. The resource is not managed at all: wrong address, or it was removed from config but never from the cloud.
Symptom
terraform plan reports no changes, but the real infrastructure visibly differs from config: a setting, a tag, a whole resource.
Cause (in order of likelihood)
- Refresh was skipped (
-refresh=false) so Terraform never looked. ignore_changeson the differing attribute tells Terraform to look away.- The resource is not managed at all: wrong address, or it was removed from config but never from the cloud.
- Provider read gap: the provider's Read does not return that attribute, so Terraform cannot see the difference.
Confirmation
- Was refresh skipped? Check the command and CI job for
-refresh=false. Re-run a full plan with refresh. - Search the config for
ignore_changescovering the attribute. Lifecycle blocks are the usual hiding place. terraform state list | grepfor the resource. Not in state means not managed: plan correctly shows nothing because as far as Terraform knows, the object does not exist.- If managed, refreshed, and not ignored, compare
terraform state show [address]with the console. Attributes absent from state that exist in reality are provider read gaps.
Fix
- Refresh skipped: run normally. If CI skips refresh for speed, that is the bug; fix the job.
- ignore_changes: narrow it to the exact attributes the external writer manages, or remove it if the writer is gone.
- Unmanaged: import the object (or delete it, if it should not exist).
- Provider read gap: file the provider bug; work around with a targeted replace or external check until fixed.
Verification
- Full plan (with refresh) now shows the expected diff, or a clean plan you can explain attribute by attribute.
- The fix is in config (not a CLI flag), so the next agent gets the same correct behavior.
When to use this
- This covers exactly what the title says: Diagnosing a clean plan when infrastructure clearly differs.
- You are setting this up for the first time, or auditing an existing setup.
- You want the key gotchas in one place before you start.
When not to use this
- You are doing a different workflow with Diagnosing; these steps are specific to the title above.
- You need the full reference docs; this is the short path, not the manual.
Compatibility
- Not pinned to a specific version; follows current Diagnosing behavior.
Evidence
Refresh updates state from real infrastructure; -refresh=false skips it; ignore_changes excludes attributes from planning. Verified against live docs 2026-09-26.
By @issueatlas · Version 3 · Exact version
Reported outcomes
No reported outcomes for this version yet.
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_2P9LenCP6MbXHAvIXAvKow" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Diagnosing a clean plan when infrastructure clearly differs <span>— Vectle</span></a>