{"record":{"id":"365d2ab3866023b9","repo":"kubernetes/kops","slug":"must-update-terraform-state-for-0-12-and-then-pas","errorCode":null,"errorMessage":"must update terraform state for 0.12, and then pass KOPS_TERRAFORM_0_12_RENAMED=ebs","messagePattern":"must update terraform state for 0\\.12, and then pass KOPS_TERRAFORM_0_12_RENAMED=ebs","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awstasks/ebsvolume.go","lineNumber":261,"sourceCode":"\tif name[0] >= '0' && name[0] <= '9' {\n\t\tusedPrefix = true\n\t\treturn fmt.Sprintf(\"ebs-%v\", name), usedPrefix\n\t}\n\treturn name, usedPrefix\n}\n\n// PreRun is run before general task execution, and checks for terraform breaking changes.\nfunc (e *EBSVolume) PreRun(c *fi.CloudupContext) error {\n\tif _, ok := c.Target.(*terraform.TerraformTarget); ok {\n\t\t_, usedPrefix := e.TerraformName()\n\t\tif usedPrefix {\n\t\t\tif os.Getenv(\"KOPS_TERRAFORM_0_12_RENAMED\") == \"\" {\n\t\t\t\tfmt.Fprintf(os.Stderr, \"Terraform 0.12 broke compatibility and disallowed names that begin with a number.\\n\")\n\t\t\t\tfmt.Fprintf(os.Stderr, \"  To move an existing cluster to the new syntax, you must first move existing volumes to the new names.\\n\")\n\t\t\t\tfmt.Fprintf(os.Stderr, \"  To indicate that you have already performed the rename, pass KOPS_TERRAFORM_0_12_RENAMED=ebs environment variable.\\n\")\n\t\t\t\tfmt.Fprintf(os.Stderr, \"  Not doing so will result in data loss.\\n\")\n\t\t\t\tfmt.Fprintf(os.Stderr, \"For detailed instructions: https://github.com/kubernetes/kops/blob/master/permalinks/terraform_renamed.md\\n\")\n\t\t\t\treturn fmt.Errorf(\"must update terraform state for 0.12, and then pass KOPS_TERRAFORM_0_12_RENAMED=ebs\")\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":243,"sourceCodeEnd":268,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awstasks/ebsvolume.go#L243-L268","documentation":"Terraform 0.12 disallowed resource names beginning with a digit, so kOps renamed EBS volume TF resources. To prevent Terraform from destroying and recreating volumes (data loss), kOps requires the operator to first migrate TF state and then opt in via the KOPS_TERRAFORM_0_12_RENAMED=ebs environment variable.","triggerScenarios":"PreRun for terraform targets targeting terraform 0.12+ syntax with EBS volumes in the cluster, when the env var is unset — kOps refuses to render to avoid silent state replacement.","commonSituations":"Upgrading an existing cluster's terraform output from the legacy digit-prefixed names to the 0.12-compatible names without migrating state first.","solutions":["Migrate each volume resource name in terraform state (terraform state mv) per the permalinks/terraform_renamed.md instructions","Export KOPS_TERRAFORM_0_12_RENAMED=ebs once state migration is complete and re-run kOps","Verify with `terraform plan` that no volumes are scheduled for replacement before applying"],"exampleFix":"// before\nkops update cluster mycluster --target=terraform\n// after\nexport KOPS_TERRAFORM_0_12_RENAMED=ebs\nkops update cluster mycluster --target=terraform","handlingStrategy":"validation","validationCode":"// Check before generating terraform\nif os.Getenv(\"KOPS_TERRAFORM_0_12_RENAMED\") != \"ebs\" && hasEBSVolumes(cluster) {\n    return errors.New(\"run terraform state mv first, then set KOPS_TERRAFORM_0_12_RENAMED=ebs\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Follow permalinks/terraform_renamed.md state-migration steps","Always run `terraform plan` and confirm zero replacements before apply","Set the env var only after state migration is verified","Snapshot/back up EBS volumes before TF renames"],"tags":["terraform","ebs","state-migration","env-var"],"backgroundTag":"terraform-012-renamed-resource","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}