{"record":{"id":"d35639c495dec685","repo":"hashicorp/terraform","slug":"error-unlocking-azure-state-lock-id-s-error","errorCode":null,"errorMessage":"Error unlocking Azure state. Lock ID: %s\n\nError: %s\n\nYou may have to force-unlock this state in order to use it again.","messagePattern":"Error unlocking Azure state\\. Lock ID: (.+?)\n\nError: (.+?)\n\nYou may have to force-unlock this state in order to use it again\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/azure/backend_state.go","lineNumber":125,"sourceCode":"\t// Grab the value\n\tif err := stateMgr.RefreshState(); err != nil {\n\t\treturn nil, diags.Append(err)\n\t}\n\t//if this isn't the default state name, we need to create the object so\n\t//it's listed by States.\n\tif v := stateMgr.State(); v == nil {\n\t\t// take a lock on this state while we write it\n\t\tlockInfo := statemgr.NewLockInfo()\n\t\tlockInfo.Operation = \"init\"\n\t\tlockId, err := client.Lock(lockInfo)\n\t\tif err != nil {\n\t\t\treturn nil, diags.Append(fmt.Errorf(\"failed to lock azure state: %s\", err))\n\t\t}\n\n\t\t// Local helper function so we can call it multiple places\n\t\tlockUnlock := func(parent error) error {\n\t\t\tif err := stateMgr.Unlock(lockId); err != nil {\n\t\t\t\treturn fmt.Errorf(strings.TrimSpace(errStateUnlock), lockId, err)\n\t\t\t}\n\t\t\treturn parent\n\t\t}\n\n\t\t// Grab the value\n\t\tif err := stateMgr.RefreshState(); err != nil {\n\t\t\terr = lockUnlock(err)\n\t\t\treturn nil, diags.Append(err)\n\t\t}\n\t\t//if this isn't the default state name, we need to create the object so\n\t\t//it's listed by States.\n\t\tif v := stateMgr.State(); v == nil {\n\t\t\t// If we have no state, we have to create an empty state\n\t\t\tif err := stateMgr.WriteState(states.NewState()); err != nil {\n\t\t\t\terr = lockUnlock(err)\n\t\t\t\treturn nil, diags.Append(err)\n\t\t\t}\n\t\t\tif err := stateMgr.PersistState(nil); err != nil {","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/remote-state/azure/backend_state.go#L107-L143","documentation":"Produced by the lockUnlock helper in StateMgr when stateMgr.Unlock(lockId) fails during cleanup of the initialization flow. Indicates the lease could not be released after a partial write/refresh failure. The message instructs the user that a manual force-unlock may be required because the lease may still be held.","triggerScenarios":"(a) Network/transport failure during the ReleaseLease call. (b) Lease ID was already released or expired. (c) Permissions revoked mid-run. (d) State blob was deleted out-of-band.","commonSituations":"Flaky network mid-init; very long init that exceeded lease validity (rare since this backend uses infinite-duration leases); operator manually broke the lease during a run.","solutions":["Run `terraform force-unlock <lock-id>` with the ID printed in the message.","Verify the lease is gone via Azure portal / `az storage blob lease show`.","If the blob was deleted, the unlock is moot — recreate the workspace state.","Retry the original terraform command once the lock is cleared."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// After a failed init that may have left a lease, attempt an explicit force-unlock.\nif err := stateMgr.Unlock(lockId); err != nil {\n    log.Printf(\"%s; capture lock id %s for manual force-unlock\", err, lockId)\n    // surface lockId to the operator / CI log\n}","preventionTips":["Always print the lock ID in CI logs so an operator can force-unlock quickly.","Use `terraform force-unlock` as a documented recovery step in runbooks.","Investigate transient network issues that interrupt the ReleaseLease call."],"tags":["azure","state-locking","lease","force-unlock","cleanup"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}