hashicorp/terraform · error · statemgr.LockError

lock ID %q does not match existing lock ID "%s/%s"

Error message

lock ID %q does not match existing lock ID "%s/%s"

What it means

In Unlock's force-unlock path (when there is no internal s.lockInfo), the caller must pass the string "<organization>/<workspace-name>" as the id. If the provided id does not equal that, the force-unlock is refused.

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 c9def3e214)

Solutions

  1. Pass exactly "<organization>/<workspace-name>" as the lock ID for force-unlock.
  2. Verify the organization and workspace names in the backend configuration.
  3. Use terraform force-unlock "<org>/<workspace>" from the CLI.

Example fix

// before: wrong format for force-unlock id
state.Unlock("some-uuid")

// after: use org/workspace as the force-unlock id
state.Unlock(s.organization + "/" + s.workspace.Name)
Defensive patterns

Strategy: validation

Validate before calling

// Construct the expected force-unlock ID and validate it
expected := organization + "/" + workspace.Name
if id != expected {
    return fmt.Errorf("force-unlock id must be %q, got %q", expected, id)
}

Try / catch

if err := state.Unlock(id); err != nil {
    var lockErr *statemgr.LockError
    if errors.As(err, &lockErr) && strings.Contains(lockErr.Err.Error(), "does not match existing lock ID") {
        // retry with the correct org/workspace id
    }
}

Prevention

When it happens

Trigger: Unlock is called on the force-unlock path with an arbitrary or wrongly-formatted id (e.g. a UUID instead of org/workspace), or targeting the wrong workspace.

Common situations: Constructing the lock ID manually and getting the format or org/workspace wrong, or pointing at a different workspace than the one locked.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/2821712689c5e623. Report an issue: GitHub.