highIntermediateSymptom-first#module#version#upgrade#breaking

Module version not pinned — breaking upgrade

terraform init -upgrade pulls a breaking module version

Likely source:configurationdeployment

Focused incident mode — strips away everything but this runbook.

Symptoms

  • terraform init -upgrade pulls a breaking module version
  • Module source has no version constraint
  • terraform plan fails after a module upgrade

Always pin module versions with ~> constraints. Untested module upgrades are the #1 cause of unexpected Terraform failures in CI.

Evidence to grab

Collect these artifacts before you change anything — they prove (or rule out) each cause.

  • Module source declarations

    grep -rn 'module "' --include='*.tf' . | grep -v version
  • Init upgrade output

    terraform init -upgrade 2>&1 | grep -E 'module|Upgraded'

Diagnostic flow

Run the steps in order, marking each claim confirmed or refuted. The evidence you gather feeds the ranked causes below.

Guided decision tree is ready.

Steps with commands, expected output, and pass/fail branches.

Ranked root causes

Evidence checklist

  • module "vpc" { source = "terraform-aws-modules/vpc/aws" } — no version
  • terraform init -upgrade pulled latest (breaking) version

Confirm before fixing

grep -rn 'source.*=' --include='*.tf' . | grep -v 'version'
READ

Find unpinned module sources

Fix

echo 'version = "~> 5.0"' >> <FILE>.tf
CHANGE

Add a version constraint to the module block

Resolution runbook

Apply from top to bottom after the cause is confirmed. Review every command before running it — risk tags are shown on each.

1
grep -rn 'source.*=' --include='*.tf' . | grep -v 'version'
READ

Find unpinned modules

2
cat .terraform/modules/modules.json | python3 -m json.tool
READ

Check installed module versions

3
echo 'version = "~> X.Y"' >> <FILE>.tf
CHANGE

Add version constraint

4
terraform init -upgrade
CHANGE

Re-resolve modules with the new constraint

5
terraform plan
READ

Verify the plan works with the pinned version

Prevention

  • Pin all module versions with ~> constraints in module blocks.
  • Use .terraform.lock.hcl for reproducible module resolution.
  • Test module upgrades in a staging workspace first.
  • Add a CI check that fails if any module source lacks a version.

Commands marked READ CHANGE DESTRUCTIVE — never run DESTRUCTIVE commands against production data you cannot restore. Copy → verify → execute.