hashicorp/terraform · error
Failed to lock cos state
Error message
Failed to lock cos state: %s
What it means
Mirror of error 180 for the COS backend. During StateMgr init for a workspace that does not yet exist, the backend acquires a lock in order to atomically create an empty state. If remoteClient.Lock returns an error, it is wrapped here.
Solutions
- Capture the Lock ID (md5) from the wrapped error and run `terraform force-unlock <LOCK_ID>`.
- Inspect the lock object in the bucket at the lock file path; remove it manually if force-unlock cannot reach it.
- Verify COS credentials have PutObject/GetObject/DeleteObject on both state and lock key prefixes.
- Avoid concurrent runs against the same workspace.
Defensive patterns
Strategy: retry
Validate before calling
// Pre-check whether a COS lock object already exists for the workspace.
func cosLockExists(c *remoteClient) (bool, error) {
exists, _, _, err := c.getObject(c.lockFile)
if err != nil {
return false, err
}
return exists, nil
} Try / catch
// Catch the lock failure, surface the lock ID, offer force-unlock.
sm, diags := backend.StateMgr(name)
if diags.HasErrors() {
msg := diags.Err().Error()
if strings.Contains(msg, "Failed to lock cos state") {
if id := extractLockID(msg); id != "" {
return fmt.Errorf("state %q locked (id=%s); run terraform force-unlock %s", name, id, id)
}
}
return diags.Err()
} Prevention
- Serialize Terraform runs per workspace via CI concurrency limits.
- Verify COS credentials have Get/Put/Delete on both state and lock key prefixes.
- Wire terraform force-unlock into the runbook for crashed runs.
- Monitor the COS bucket for orphaned lock files.
When it happens
Trigger: Backend.StateMgr(name) where name is not in Workspaces(); c.Lock(lockInfo) returns an error — typically cosLock fails, the lock file already exists, or COS putObject of the lock info fails.
Common situations: A stale lock object in the COS bucket from a previous crashed run; a concurrent Terraform run holding the lock; COS credentials lack PutObject on the lock file key; network/COS 5xx.
Related errors
- lock file exists
- lock id mismatch, !=
- Unlocking the state file on TencentCloud cos backend…
- acl value invalid, expected
- default state is not allowed to be deleted
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/419fcd76a3b7e590.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/cos/backend_state.go:115
}
exists := false
for _, candidate := range ws {
if candidate == name {
exists = true
break
}
}
if !exists {
log.Printf("[DEBUG] workspace %v not exists", name)
// take a lock on this state while we write it
lockInfo := statemgr.NewLockInfo()
lockInfo.Operation = "init"
lockId, err := c.Lock(lockInfo)
if err != nil {
return nil, diags.Append(fmt.Errorf("Failed to lock cos state: %s", err))
}
// Local helper function so we can call it multiple places
lockUnlock := func(e error) error {
if err := stateMgr.Unlock(lockId); err != nil {
return fmt.Errorf(unlockErrMsg, err, lockId)
}
return e
}
// Grab the value
if err := stateMgr.RefreshState(); err != nil {
err = lockUnlock(err)
return nil, diags.Append(err)
}
// If we have no state, we have to create an empty state
if v := stateMgr.State(); v == nil {View on GitHub (pinned to d32a084675)