hashicorp/terraform · critical

confirmFunc must not be nil

Error message

confirmFunc must not be nil

What it means

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.

Source

Thrown at internal/command/meta_backend_migrate.go:443

			// this later prompt for Cloud, even though we do still need it
			// for state backends.
			confirmFunc = func(statemgr.Full, statemgr.Full, *backendMigrateOpts) (bool, error) {
				return true, nil // the answer is implied to be "yes" if we reached this point
			}
		} else {
			log.Print("[TRACE] backendMigrateState: destination workspace has empty state, so might copy source workspace state")
			confirmFunc = m.backendMigrateEmptyConfirm
		}

	// Both states are non-empty, meaning we need to determine which
	// state should be used and update accordingly.
	case !source.Empty() && !destination.Empty():
		log.Print("[TRACE] backendMigrateState: both source and destination workspaces have states, so might overwrite destination with source")
		confirmFunc = m.backendMigrateNonEmptyConfirm
	}

	if confirmFunc == nil {
		panic("confirmFunc must not be nil")
	}

	if !opts.force {
		// Abort if we can't ask for input.
		if !m.input {
			log.Print("[TRACE] backendMigrateState: can't prompt for input, so aborting migration")
			return errors.New(strings.TrimSpace(errInteractiveInputDisabled))
		}

		// Confirm with the user whether we want to copy state over
		confirm, err := confirmFunc(sourceState, destinationState, opts)
		if err != nil {
			log.Print("[TRACE] backendMigrateState: error reading input, so aborting migration")
			return err
		}
		if !confirm {
			log.Print("[TRACE] backendMigrateState: user cancelled at confirmation prompt, so aborting migration")
			return nil

View on GitHub (pinned to d32a084675)

Solutions

  1. Report as a Terraform bug; include the backend types and whether either state was empty.
  2. Workaround: ensure at least one side (source or destination) has non-empty state before running terraform state migrate / init -migrate-state.
  3. Try terraform state push/pull to seed one side and avoid the empty/empty branch.

Example fix

// before (library code)
if confirmFunc == nil {
    panic("confirmFunc must not be nil")
}

// after (defensive)
if confirmFunc == nil {
    return fmt.Errorf("no migration strategy determined for source-empty=%v dest-empty=%v", source.Empty(), destination.Empty())
}
Defensive patterns

Strategy: try-catch

Try / catch

// Defensive: return an error instead of panicking on unhandled case
if confirmFunc == nil {
    return fmt.Errorf("no migration strategy for source-empty=%v dest-empty=%v", source.Empty(), destination.Empty())
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/8a34a03fc104ff89. Report an issue: GitHub.