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

  1. Check the workspace run queue and lock status in the HCP Terraform / TFE UI to confirm who holds the lock
  2. If the lock is stale (the holder is no longer active), use terraform force-unlock or the UI Force Unlock button
  3. Wait for the current run to complete and release the lock naturally
  4. 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

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


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 so

View on GitHub (pinned to d32a084675)