hashicorp/terraform · error · LockError
lock id does not match existing lock
Error message
lock id %q does not match existing lock
What it means
Returned as a statemgr.LockError when Unlock(id) is called with an id that does not match lease.Spec.HolderIdentity (client.go:320-323). The %q is the supplied id. The lock info is attached so callers can report who actually holds the lock. This protects against one run releasing another's lock.
Solutions
- Use the lock ID returned by the Lock call that acquired THIS lock — do not reuse IDs across runs.
- Inspect the attached LockError.Info to see who actually holds the lock and coordinate with them.
- If the holder is stale/orphaned, force-unlock using the correct existing lock ID (from LockError.Info.ID).
- Serialize access to the workspace so only one run holds the lock at a time.
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the lock ID matches the current holder before unlocking:
// lease, _ := getLease(name)
// if lease.Spec.HolderIdentity != nil && *lease.Spec.HolderIdentity != id { /* mismatch */ } Try / catch
// if err := client.Unlock(id); err != nil {
// var le *statemgr.LockError
// if errors.As(err, &le) && le.Info != nil {
// actualHolder := le.Info.ID // coordinate with this owner
// }
// } Prevention
- Always use the lock ID returned by the Lock call that acquired the lock for this run.
- Never hard-code or cache lock IDs across runs.
- Inspect LockError.Info to identify the real holder before force-unlocking.
When it happens
Trigger: Passing a stale or foreign lock ID to Unlock; a lock ID from a previous run persisted and reused; concurrent runs where one tries to unlock the other's lease.
Common situations: An old lock ID cached in state/scripts; a CI job reusing a lock ID from a prior failed run; manual force-unlock with the wrong ID; two pipelines targeting the same workspace.
Related errors
- lock ID does not match existing lock ( )
- lock ID ' ' does not match the existing lock ID
- state is already unlocked
- failed to delete the lock file
- failed to read the body of the S3 object
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/344e31d086dda324.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/kubernetes/client.go:322
}
lease, err := c.getLease(leaseName)
if err != nil {
return err
}
if lease.Spec.HolderIdentity == nil {
return fmt.Errorf("state is already unlocked")
}
lockInfo, err := c.getLockInfo(lease)
if err != nil {
return err
}
lockErr := &statemgr.LockError{Info: lockInfo}
if *lease.Spec.HolderIdentity != id {
lockErr.Err = fmt.Errorf("lock id %q does not match existing lock", id)
return lockErr
}
lease.Spec.HolderIdentity = nil
removeLockInfo(lease)
_, err = c.kubernetesLeaseClient.Update(context.Background(), lease, metav1.UpdateOptions{})
if err != nil {
lockErr.Err = err
return lockErr
}
return nil
}
func (c *RemoteClient) getLockInfo(lease *coordinationv1.Lease) (*statemgr.LockInfo, error) {
lockData, ok := getLockInfo(lease)
if len(lockData) == 0 || !ok {View on GitHub (pinned to d32a084675)