hashicorp/terraform · error
(lock ID: " / ")
Error message
%s (lock ID: "%s/%s")
What it means
Thrown during Lock when the TFE Workspaces.Lock API returns tfe.ErrWorkspaceLocked, meaning the workspace is already locked. The error message appends the organization and workspace name so the user can identify which workspace holds the conflicting lock. The full error is wrapped in a statemgr.LockError so the caller can surface lock metadata.
Solutions
- Check the workspace run queue and lock status in the HCP Terraform / TFE UI to confirm who holds the lock
- If the lock is stale (the holder is no longer active), use terraform force-unlock or the UI Force Unlock button
- Wait for the current run to complete and release the lock naturally
- Investigate CI orchestration to prevent concurrent applies to the same workspace (use workspace-level queueing)
Defensive patterns
Strategy: validation
Validate before calling
// Before calling Lock, check if the workspace is already locked:
ws, err := tfeClient.Workspaces.Read(ctx, organization, workspaceName)
if err != nil {
return err
}
if ws.Locked {
return fmt.Errorf("workspace %s/%s is already locked; run 'terraform force-unlock' if the lock is stale", organization, workspaceName)
} Try / catch
id, err := stateMgr.Lock(lockInfo)
if err != nil {
var lockErr *statemgr.LockError
if errors.As(err, &lockErr) && strings.Contains(err.Error(), "lock ID:") {
// workspace already locked — prompt user or auto-wait
return handleExistingLock(lockErr)
}
return err
} Prevention
- Prevent concurrent CI jobs targeting the same workspace with orchestration-level locking
- After a crashed apply, always run 'terraform force-unlock' or unlock via the TFE UI before the next run
- Use workspace auto-queue in HCP Terraform rather than parallel CI pipelines to serialize runs
When it happens
Trigger: A previous terraform run crashed or was killed without releasing its lock; a user manually locked the workspace in the HCP Terraform / TFE UI; another CI job or teammate is currently running apply on the same workspace; a speculative plan holds the lock.
Common situations: CI pipeline cancelled mid-apply leaving a dangling lock; developer locked a workspace for investigation and forgot; concurrent terraform runs in branching CI workflows targeting one workspace; TFE run that errored but did not auto-unlock.
Related errors
- (lock ID: " / ")
- error deleting workspace
- error deleting workspace
- error loading workspace
- error loading workspace
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/d1f1e165803cdefd.
Report an issue: GitHub.
Appendix: source
Thrown at internal/cloud/state.go:352
func (s *State) Lock(info *statemgr.LockInfo) (string, error) {
s.mu.Lock()
defer s.mu.Unlock()
if s.disableLocks {
return "", nil
}
ctx := context.Background()
lockErr := &statemgr.LockError{Info: s.lockInfo}
// Lock the workspace.
_, err := s.tfeClient.Workspaces.Lock(ctx, s.workspace.ID, tfe.WorkspaceLockOptions{
Reason: tfe.String("Locked by Terraform"),
})
if err != nil {
if err == tfe.ErrWorkspaceLocked {
lockErr.Info = info
err = fmt.Errorf("%s (lock ID: \"%s/%s\")", err, s.organization, s.workspace.Name)
}
lockErr.Err = err
return "", lockErr
}
s.lockInfo = info
return s.lockInfo.ID, nil
}
// statemgr.Refresher impl.
func (s *State) RefreshState() error {
s.mu.Lock()
defer s.mu.Unlock()
return s.refreshState()
}
// refreshState is the main implementation of RefreshState, but split out soView on GitHub (pinned to d32a084675)