hashicorp/terraform · error
error unmarshaling lock info
Error message
error unmarshaling lock info: %s
What it means
RemoteClient.getLockInfo reads the KV pair at path+lockInfoSuffix and json.Unmarshal's its value into statemgr.LockInfo. If the bytes are not valid JSON for that schema, this fires. The lock info key is malformed.
Solutions
- Read the raw bytes: `consul kv get <path>.lock` and inspect the content.
- If malformed and no Terraform run is active, delete it: `consul kv delete <path>.lock` after confirming.
- Standardize the Terraform version across the team so LockInfo schemas agree.
- Audit Consul KV usage to ensure no other writer is touching the lock suffix key.
Defensive patterns
Strategy: validation
Validate before calling
// Before locking/unlocking, sanity-check the lock info key is valid JSON.
func lockInfoValid(client *consulapi.Client, statePath string) error {
pair, _, err := client.KV().Get(strings.TrimRight(statePath, "/")+".lock", nil)
if err != nil || pair == nil {
return nil
}
var li statemgr.LockInfo
if err := json.Unmarshal(pair.Value, &li); err != nil {
return fmt.Errorf("lock info at %s.lock is corrupt: %w", statePath, err)
}
return nil
} Prevention
- Standardize the Terraform version across the team to keep LockInfo schemas aligned.
- Never manually write to the .lock suffix key.
- Periodically inspect the lock key only with consul kv get, never with writers.
- After incidents, clean up malformed lock keys before re-running.
When it happens
Trigger: getLockInfo -> pair != nil -> json.Unmarshal(pair.Value, li) returns a non-nil error.
Common situations: A lock info key was written by an incompatible Terraform version with a different LockInfo schema; someone manually wrote a non-JSON payload at the .lock suffix key; Consul returned partial bytes from a corrupted snapshot; another tool collided on the same key namespace.
Related errors
- Error unlocking Consul state. Lock ID
- failed to lock state in Consul
- Key could not be found
- state already locked
- The remote state does not match the expected hash
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/6d0087245c8b219b.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/consul/client.go:356
}, nil)
return err
}
func (c *RemoteClient) getLockInfo() (*statemgr.LockInfo, error) {
path := c.lockPath() + lockInfoSuffix
pair, _, err := c.Client.KV().Get(path, nil)
if err != nil {
return nil, err
}
if pair == nil {
return nil, nil
}
li := &statemgr.LockInfo{}
err = json.Unmarshal(pair.Value, li)
if err != nil {
return nil, fmt.Errorf("error unmarshaling lock info: %s", err)
}
return li, nil
}
func (c *RemoteClient) Lock(info *statemgr.LockInfo) (string, error) {
c.mu.Lock()
defer c.mu.Unlock()
if !c.lockState {
return "", nil
}
c.info = info
// These checks only are to ensure we strictly follow the specification.
// Terraform shouldn't ever re-lock, so provide errors for the 2 possible
// states if this is called.View on GitHub (pinned to d32a084675)