## TL;DR
Changing the backend block invalidates the cached backend configuration, so terraform demands re-initialization before any operation. Back up the state, run terraform init -migrate-state to move it to the new backend, and verify with a no-change plan. In automation, pre-answer the migration prompt explicitly rather than letting a headless agent hang on it.

## The query

```text
terraform error: Backend initialization required before apply after migrating state backend
```

## Use this when

- terraform apply fails with "Backend initialization required"
- The backend block was changed (s3 to remote, local to s3, etc.)
- An agent edited backend config and every command now errors
- CI started failing right after a backend migration commit

## Not for

- Provider initialization errors (fix provider config, not the backend)
- State lock timeouts (a different lock, a different fix)
- Corrupt state files (restore from backup first)

## Steps

### 1. Back up the current state

```bash
terraform state pull > [backup dir]/terraform.tfstate.backup
```

If the backend is local, copy terraform.tfstate. Expected output: a complete state file saved outside the working directory. Backend migrations move the only copy of your infrastructure record: back it up first, every time.

### 2. Re-initialize with state migration

```bash
terraform init -migrate-state
```

Terraform asks whether to copy the existing state to the new backend. Answer yes after confirming the backup from step 1. Expected output: "Terraform has been successfully initialized" and a confirmation that the state was migrated.

### 3. For headless agents: pre-answer explicitly

```bash
terraform init -migrate-state -input=false
```

With -input=false terraform will not prompt; ensure the migration answer is acceptable by running the interactive version once on a scratch copy first, or set the backend config so no ambiguity exists. Never let an agent sit on an unanswered prompt: it burns the tool timeout and leaves init half-done.

Expected output: init completes without prompting. If it errors asking for input, the backend config is ambiguous: fix the config, do not remove -input=false.

### 4. Verify the state landed intact

```bash
terraform plan
```

Expected output: either no changes, or only the changes you expect. A plan that wants to recreate everything means the state did not migrate: stop and restore the backup, do not apply.

### 5. Lock the backend config after migration

Commit the new backend block, document the migration in the runbook, and remove any stale backend config from other branches. Expected output: the next init on any machine picks up the new backend with no prompts.

## Tool compatibility

terraform 1.x. init -migrate-state and -reconfigure flags are stable across 1.x.

## Variant phrasings

### terraform Backend initialization required before apply

Step 2: terraform init -migrate-state is the fix; plain init without -migrate-state leaves the state behind.

### terraform backend migration init hangs on prompt

Step 3: the agent must not wait on the prompt. Pre-answer with -input=false after a rehearsed interactive run.

### terraform init -migrate-state vs -reconfigure

Use -migrate-state to copy state to the new backend; use -reconfigure when you only want to switch config without moving state.

## Why it happens

Terraform caches the backend configuration in .terraform. Changing the backend block makes the cache stale, and terraform refuses to operate until init reconciles it. The -migrate-state flag additionally copies the state itself, because the new backend starts empty and an empty state plus real infrastructure looks like "create everything" to the next plan.

## Edge cases

- If the old backend is unreachable (deleted bucket, revoked creds), -migrate-state cannot pull: restore the backup into the new backend with terraform state push after init -reconfigure.
- Two engineers migrating the backend concurrently can fork the state: coordinate so exactly one migration runs, then everyone else re-inits.
- Partial migration (state copied but old backend still configured somewhere) causes split-brain plans: verify every workspace and CI job points at the new backend.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_tEFfxgVhu_28KHLosNfhkA
