{"record":{"id":"8a34a03fc104ff89","repo":"hashicorp/terraform","slug":"confirmfunc-must-not-be-nil","errorCode":null,"errorMessage":"confirmFunc must not be nil","messagePattern":"confirmFunc must not be nil","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"internal/command/meta_backend_migrate.go","lineNumber":443,"sourceCode":"\t\t\t// this later prompt for Cloud, even though we do still need it\n\t\t\t// for state backends.\n\t\t\tconfirmFunc = func(statemgr.Full, statemgr.Full, *backendMigrateOpts) (bool, error) {\n\t\t\t\treturn true, nil // the answer is implied to be \"yes\" if we reached this point\n\t\t\t}\n\t\t} else {\n\t\t\tlog.Print(\"[TRACE] backendMigrateState: destination workspace has empty state, so might copy source workspace state\")\n\t\t\tconfirmFunc = m.backendMigrateEmptyConfirm\n\t\t}\n\n\t// Both states are non-empty, meaning we need to determine which\n\t// state should be used and update accordingly.\n\tcase !source.Empty() && !destination.Empty():\n\t\tlog.Print(\"[TRACE] backendMigrateState: both source and destination workspaces have states, so might overwrite destination with source\")\n\t\tconfirmFunc = m.backendMigrateNonEmptyConfirm\n\t}\n\n\tif confirmFunc == nil {\n\t\tpanic(\"confirmFunc must not be nil\")\n\t}\n\n\tif !opts.force {\n\t\t// Abort if we can't ask for input.\n\t\tif !m.input {\n\t\t\tlog.Print(\"[TRACE] backendMigrateState: can't prompt for input, so aborting migration\")\n\t\t\treturn errors.New(strings.TrimSpace(errInteractiveInputDisabled))\n\t\t}\n\n\t\t// Confirm with the user whether we want to copy state over\n\t\tconfirm, err := confirmFunc(sourceState, destinationState, opts)\n\t\tif err != nil {\n\t\t\tlog.Print(\"[TRACE] backendMigrateState: error reading input, so aborting migration\")\n\t\t\treturn err\n\t\t}\n\t\tif !confirm {\n\t\t\tlog.Print(\"[TRACE] backendMigrateState: user cancelled at confirmation prompt, so aborting migration\")\n\t\t\treturn nil","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/command/meta_backend_migrate.go#L425-L461","documentation":"Programmer-error panic in backendMigrateState: after the switch over source/destination emptiness, confirmFunc must have been assigned (backendMigrateEmptyConfirm for empty-destination, backendMigrateNonEmptyConfirm for both-non-empty, etc.). If none of the cases matched, confirmFunc stays nil and the function panics rather than dereferencing a nil function pointer later.","triggerScenarios":"The switch failed to assign confirmFunc for a particular combination of source/destination state presence (e.g. both empty, or some other combination the code did not anticipate).","commonSituations":"Edge case in state migration where both source and destination states are empty, or a refactor that changed the case conditions without covering all branches.","solutions":["Report as a Terraform bug; include the backend types and whether either state was empty.","Workaround: ensure at least one side (source or destination) has non-empty state before running terraform state migrate / init -migrate-state.","Try terraform state push/pull to seed one side and avoid the empty/empty branch."],"exampleFix":"// before (library code)\nif confirmFunc == nil {\n    panic(\"confirmFunc must not be nil\")\n}\n\n// after (defensive)\nif confirmFunc == nil {\n    return fmt.Errorf(\"no migration strategy determined for source-empty=%v dest-empty=%v\", source.Empty(), destination.Empty())\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Defensive: return an error instead of panicking on unhandled case\nif confirmFunc == nil {\n    return fmt.Errorf(\"no migration strategy for source-empty=%v dest-empty=%v\", source.Empty(), destination.Empty())\n}","preventionTips":["Ensure at least one side of a migration has non-empty state before running.","Report empty/empty or other unhandled combinations as a Terraform bug.","Use terraform state push/pull to seed state as a workaround."],"tags":["terraform","backend","state-migration","panic","internal-bug"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}