hashicorp/terraform · error

could not write lock info for

Error message

could not write lock info for %q: %s

What it means

Thrown by LocalState.writeLockInfo when ioutil.WriteFile fails to persist the lock info JSON to the .tflock file with mode 0600. This runs during Lock to record who/what holds the lock. Failure means the lock info could not be written, even though the in-process and on-disk lock acquisition may have partly succeeded.

Solutions

  1. Ensure the state file's directory is writable by the current user.
  2. Remove or chown a stale .tflock file left by a prior root run: `sudo rm <statefile>.tflock`.
  3. Check disk space and that the filesystem is mounted read-write.
  4. Move state to a writable location and update -state or the backend config.
Defensive patterns

Strategy: validation

Validate before calling

func stateDirWritable(statePath string) error {
    dir, _ := filepath.Split(statePath)
    if dir == "" { dir = "." }
    probe, err := os.CreateTemp(dir, ".lock-test-*")
    if err != nil { return fmt.Errorf("cannot write lock info in %s: %w", dir, err) }
    probe.Close(); os.Remove(probe.Name())
    return nil
}

Prevention

When it happens

Trigger: The state file's directory is not writable; disk full; the path is on a read-only filesystem; permission denied on the existing .tflock file (owned by another user).

Common situations: State file on a read-only mount; CI environment where the state dir has restricted perms; a previous root-owned .tflock file blocking the current user; out-of-disk.

Related errors


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

Appendix: source

Thrown at internal/command/clistate/local_state.go:312

	}

	info := statemgr.LockInfo{}
	err = json.Unmarshal(infoData, &info)
	if err != nil {
		return nil, fmt.Errorf("state file %q locked, but could not unmarshal lock info: %s", s.Path, err)
	}
	return &info, nil
}

// write a new lock info file
func (s *LocalState) writeLockInfo(info *statemgr.LockInfo) error {
	path := s.lockInfoPath()
	info.Path = s.Path
	info.Created = time.Now().UTC()

	err := ioutil.WriteFile(path, info.Marshal(), 0600)
	if err != nil {
		return fmt.Errorf("could not write lock info for %q: %s", s.Path, err)
	}
	return nil
}

View on GitHub (pinned to d32a084675)