hashicorp/terraform · error

failed to write state

Error message

failed to write state: %w

What it means

Thrown by Local.opRefresh after a successful refresh when statemgr.WriteAndPersist(opState, newState, schemas) returns a non-nil error while writing the refreshed state back to disk (or to the wrapped remote backend). The refresh itself succeeded; only persistence failed.

Solutions

  1. Free up disk space or move TF_DATA_DIR / the state path to a writable volume.
  2. For remote backends, verify the credentials still have PutObject/storage.objectAdmin and that any state size cap (e.g. S3 object size, DynamoDB lock table) is not exceeded.
  3. Ensure no other terraform process holds the state lock; rely on the StateLocker rather than disabling it.
  4. Retry after fixing the underlying I/O issue; the refreshed state is in memory and can be re-persisted on the next run.

Example fix

null
Defensive patterns

Strategy: retry

Validate before calling

// Preflight: writable state target with free space.
func stateWritable(path string) error {
    dir := filepath.Dir(path)
    var stat unix.Statfs_t
    if err := unix.Statfs(dir, &stat); err != nil { return err }
    if stat.Bavail*uint64(stat.Bsize) < 1<<20 { return fmt.Errorf("low disk space on %s", dir) }
    return os.WriteFile(filepath.Join(dir, ".wprobe"), []byte{}, 0o644)
}

Type guard

null

Try / catch

err := statemgr.WriteAndPersist(opState, newState, schemas)
if err != nil {
    if isTransient(err) { // retry once after backoff
        time.Sleep(500 * time.Millisecond)
        err = statemgr.WriteAndPersist(opState, newState, schemas)
    }
    if err != nil { diags = diags.Append(fmt.Errorf("failed to write state: %w", err)) }
}

Prevention

When it happens

Trigger: WriteAndPersist returns err: the state file path is not writable, the disk is full, a remote backend PUT was rejected (e.g. size limit, lost permissions), or the state lock was released by a competing process. The error is appended to diags and reported via op.ReportResult.

Common situations: Out of disk space on the volume holding terraform.tfstate; a remote backend (S3, GCS, etc.) where the credentials lost write permission between plan and refresh; concurrent terraform runs racing on the same state file; antivirus locking the file on Windows during write.

Related errors


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

Appendix: source

Thrown at internal/backend/local/backend_refresh.go:112

		newState, refreshDiags = lr.Core.Refresh(lr.Config, lr.InputState, lr.PlanOpts)
		log.Printf("[INFO] backend/local: refresh calling Refresh")
	}()

	if b.opWait(doneCh, stopCtx, cancelCtx, lr.Core, opState, op.View) {
		return
	}

	// Write the resulting state to the running op
	runningOp.State = newState
	diags = diags.Append(refreshDiags)
	if refreshDiags.HasErrors() {
		op.ReportResult(runningOp, diags)
		return
	}

	err := statemgr.WriteAndPersist(opState, newState, schemas)
	if err != nil {
		diags = diags.Append(fmt.Errorf("failed to write state: %w", err))
		op.ReportResult(runningOp, diags)
		return
	}

	// Show any remaining warnings before exiting
	op.ReportResult(runningOp, diags)
}

View on GitHub (pinned to d32a084675)