A state-lock error does not automatically mean a stale lock. Your terminal may have ended while a CI runner or another job still owns the same state. Ignoring the lock can turn a waiting problem into concurrent writes.
First confirm that it is the same lock
Record Lock ID, Operation, Who, Created and Path alongside the backend and workspace, omitting secrets. Correlate the CI run, its status and runner process. For example, a laptop plan blocked by an active apply job on the same workspace is normal exclusion. An old Created timestamp alone does not establish that the owner is dead.
The Terraform locking documentation describes backend support and the requirement to establish ownership of a leftover lock. Running with -lock=false does not establish that ownership. One Ctrl+C does not inevitably create a stale lock either.
Distinguish active, unknown and confirmed terminated
For an active run, wait or use its normal cancellation procedure. If the runner is inaccessible and ownership is unknown, record unlock as deferred. Once the owner is confirmed terminated and new writers are coordinated for the same backend and workspace, preserve backend audit records and state versions or backups before considering the documented unlock procedure. Never guess an ID or reuse one from another workspace.
After an unlock, review proposed changes, deletions and replacements before any apply. A missing lock does not prove that resources and state agree. No remote state or force-unlock was used here; this is not a report of recovery on a particular backend.