hashicorp/terraform · error
could not write lock info for %q: %s
Error message
could not write lock info for %q: %s
What it means
Returned by LocalState.writeLockInfo (local_state.go:305) when ioutil.WriteFile fails to create/overwrite the lock info metadata file (.terraform.tfstate.lock.info) with mode 0600. writeLockInfo is the final step of Lock after the OS-level file lock (s.lock) succeeded; it persists the LockInfo record so other processes can identify the lock holder. Failure here means the lock is held but not documented.
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 c9def3e214)
Solutions
- Check write permission on the directory containing the state file: `ls -ld $(dirname <statefile>)` and `touch <dir>/.write-test`.
- Ensure the state directory exists and is writable by the Terraform process: `mkdir -p .terraform && chmod u+w .terraform`.
- Free disk space if the volume is full.
- If the directory was deleted mid-run, recreate it and re-run; call `terraform force-unlock` to clean up any half-acquired lock before retrying.
Example fix
# before $ terraform plan could not write lock info for "terraform.tfstate": open .terraform.tfstate.lock.info: permission denied # after $ chmod u+w . $ terraform force-unlock <id> # clear any partial lock $ terraform plan
Defensive patterns
Strategy: validation
Validate before calling
// Ensure the state directory is writable before locking
stateDir := filepath.Dir(s.Path)
if err := os.MkdirAll(stateDir, 0755); err != nil {
return fmt.Errorf("state dir unusable: %w", err)
}
probe := filepath.Join(stateDir, ".write-probe")
if err := ioutil.WriteFile(probe, []byte(""), 0600); err != nil {
return fmt.Errorf("state dir not writable: %w", err)
}
os.Remove(probe) Try / catch
// If writeLockInfo fails after acquiring the OS lock, attempt to release the OS lock to avoid a held-but-undocumented lock.
if err := s.writeLockInfo(info); err != nil {
if uerr := s.unlock(); uerr != nil {
log.Printf("warning: failed to write lock info (%v) and failed to roll back OS lock (%v)", err, uerr)
}
s.lockID = ""
return fmt.Errorf("could not persist lock info: %w", err)
} Prevention
- Pre-flight check write permission on the state directory.
- Keep the state directory on local, writable storage.
- In CI, create the state directory explicitly before running Terraform.
- Document the lock info file path so operators can inspect it.
When it happens
Trigger: ioutil.WriteFile returns an error: the state directory is read-only or missing, permission denied on the directory, disk full, path too long, or the process lost write permission between acquiring the file lock and writing the metadata.
Common situations: The state directory is on a read-only mount; another user owns the directory; the directory was deleted between locking and writing info; disk filled up; running in a sandbox that allows file locking but not file creation.
Related errors
- state %q already locked
- LocalState not locked
- invalid lock id: %q. current id: %q
- state file %q locked, but could not unmarshal lock info: %s
- error deleting workspace %s: %w
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/b3b82e05845b4b16.
Report an issue: GitHub.