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
- Ensure the state file's directory is writable by the current user.
- Remove or chown a stale .tflock file left by a prior root run: `sudo rm <statefile>.tflock`.
- Check disk space and that the filesystem is mounted read-write.
- 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
- Keep the state file's directory writable by all users who run Terraform.
- Remove stale root-owned .tflock files before non-root runs.
- Avoid read-only mounts for local state.
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
- invalid lock id: . current id
- LocalState not locked
- state file locked, but could not unmarshal lock info
- state already locked
- backendDiags.Err()
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)