hashicorp/terraform · error
lock ID does not match existing lock ID " /
Error message
lock ID %q does not match existing lock ID "%s/%s"
What it means
Thrown during Unlock when s.lockInfo is nil (no normal lock was held, implying a force-unlock attempt) but the caller-supplied id does not match the expected org/workspace format (organization/workspaceName). This validates that the caller is intentionally force-unlocking the correct workspace before calling Workspaces.ForceUnlock.
Solutions
- When force-unlocking, pass the ID in the exact format "organization/workspaceName"
- Ensure Lock is called before Unlock in the normal flow so s.lockInfo is populated
- If using the terraform CLI, use 'terraform force-unlock <LOCK_ID>' which formats the ID correctly
Defensive patterns
Strategy: validation
Validate before calling
// For force-unlock, construct the expected ID and validate it:
expectedID := organization + "/" + workspaceName
if forceUnlockID != expectedID {
return fmt.Errorf("force-unlock ID must be %q, got %q", expectedID, forceUnlockID)
} Try / catch
err := stateMgr.Unlock(id)
if err != nil && strings.Contains(err.Error(), "does not match existing lock ID") {
// force-unlock ID format is wrong; inform user of the expected format
return fmt.Errorf("use lock ID %q for force-unlock of %s/%s", org+"/"+ws, org, ws)
}
return err Prevention
- For force-unlock via the cloud State type, always use the 'organization/workspaceName' format
- Prefer the terraform CLI 'terraform force-unlock' command which formats IDs correctly
- Do not mix normal-lock IDs with force-unlock IDs in the same code path
When it happens
Trigger: Force-unlock attempted with an ID that does not match the "organization/workspaceName" pattern; s.lockInfo was cleared or never set but Unlock is called with a leftover normal-lock ID; misconfigured state manager that skipped the Lock phase but still tries to Unlock.
Common situations: Programmatic usage of the cloud State type outside the normal statemgr lifecycle; a state manager reused after a failed initialization; testing code that constructs State manually without going through the backend factory.
Related errors
- lock ID does not match existing lock ID " /
- error uploading state
- lock ID does not match existing lock
- lock ID does not match existing lock
- (lock ID: " / ")
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/2821712689c5e623.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cloud/state.go:503
return err
}
// This will not be retried
return &errorUnlockFailed{innerError: err}
}
return nil
})
if err != nil {
lockErr.Err = err
return lockErr
}
return nil
}
// Verify the optional force-unlock lock ID.
if s.organization+"/"+s.workspace.Name != id {
lockErr.Err = fmt.Errorf(
"lock ID %q does not match existing lock ID \"%s/%s\"",
id,
s.organization,
s.workspace.Name,
)
return lockErr
}
// Force unlock the workspace.
_, err := s.tfeClient.Workspaces.ForceUnlock(ctx, s.workspace.ID)
if err != nil {
lockErr.Err = err
return lockErr
}
return nil
}
View on GitHub (pinned to d32a084675)