Error: Saved plan is stale
Fixes terraform's "Error: Saved plan is stale" failure. Use when applying a saved plan file fails because another operation changed the state after the plan was created. Explains the lineage/serial check and the re-plan fix. Not for drift shown in fresh plans or lock contention.
Fix terraform "Error: Saved plan is stale"
TL;DR: The state changed after you created the plan file, so the saved plan is no longer safe to apply. A plan records the state's lineage and serial; when apply sees the state has moved, it refuses. Re-run terraform plan to make a fresh plan against the current state, then apply that.
The error
Error: Saved plan is stale
The given plan file can no longer be applied because the state was changed by another operation after the plan was created.Steps
- Find what moved the state: ask the team, check CI runs, or look at recent apply logs. Expected: you identify the apply that landed after your plan.
- Re-run
terraform plan -out=tfplan. Expected: the new plan is computed against the current state. - Review the fresh plan, then
terraform apply tfplan. Expected: apply proceeds because lineage and serial match. - To stop it recurring, serialize plan and apply per workspace in CI so two pipelines cannot interleave. Expected: no more parallel-plan races.
When this applies
terraform apply tfplanfails with "Saved plan is stale" and the message about state changing after plan creation.- Two PRs or pipelines planned against the same workspace and the first one applied first.
When it does NOT apply
- Plan shows unexpected changes (drift). That is normal planning against current state, not a stale saved plan.
- You never saved a plan file. Plain
terraform applyplans and applies in one go and cannot hit this.
Tool and version compatibility
- All Terraform CLI versions. The lineage and serial check on saved plans has always been there.
Why it happens
A saved plan is a promise: "apply exactly this, against exactly the state I saw." Terraform embeds the state's lineage and serial number in the plan file and verifies them at apply time. If any other operation wrote state in between, the promise is void and Terraform refuses rather than apply a plan computed against a world that no longer exists.
Edge cases and pitfalls
- A plan file records nothing about your git commit. A plan made at commit A applies fine at commit B as long as the state never moved; review the code the plan was made from, not just the plan.
- Do not "fix" this with
-lock=false. The staleness check is protecting you from a concurrent writer; disabling the lock makes the race worse.