{"record":{"id":"b570370c2dc11344","repo":"hashicorp/terraform","slug":"error-unlocking-alibaba-cloud-oss-state-file-loc","errorCode":null,"errorMessage":"Error unlocking Alibaba Cloud OSS state file:\n\nLock ID: %s\nError message: %#v\n\nYou may have to force-unlock this state in order to use it again.\nThe Alibaba Cloud backend acquires a lock during initialization to ensure the initial state file is created.","messagePattern":"Error unlocking Alibaba Cloud OSS state file:\n\nLock ID: (.+?)\nError message: %#v\n\nYou may have to force-unlock this state in order to use it again\\.\nThe Alibaba Cloud backend acquires a lock during initialization to ensure the initial state file is created\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/oss/backend_state.go","lineNumber":157,"sourceCode":"\t\tif s == name {\n\t\t\texists = true\n\t\t\tbreak\n\t\t}\n\t}\n\t// We need to create the object so it's listed by States.\n\tif !exists {\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 OSS state: %s\", err))\n\t\t}\n\n\t\t// Local helper function so we can call it multiple places\n\t\tlockUnlock := func(e error) error {\n\t\t\tif err := stateMgr.Unlock(lockId); err != nil {\n\t\t\t\treturn fmt.Errorf(strings.TrimSpace(stateUnlockError), lockId, err)\n\t\t\t}\n\t\t\treturn e\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\n\t\t// If we have no state, we have to create an empty state\n\t\tif v := stateMgr.State(); v == nil {\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 {\n\t\t\t\terr = lockUnlock(err)","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/oss/backend_state.go#L139-L175","documentation":"The stateUnlockError template (backend_state.go:200-208) used inside StateMgr's lockUnlock helper (backend_state.go:155-159). It fires when stateMgr.Unlock(lockId) fails after the backend already acquired an init lock for a new workspace. The error tells the user the lock may be left dangling and points them at force-unlock.","triggerScenarios":"During first-use state initialization, after successfully Lock()-ing, a subsequent step (RefreshState/WriteState/PersistState) fails and the cleanup Unlock() also fails, so the error returned to the user combines the original failure with this unlock-failure message naming the lockId.","commonSituations":"OTS transient failure exactly during the unlock window; OTS table deleted mid-init; RAM permissions changed mid-run; lock row was concurrently removed by another force-unlock, making the conditional delete behave unexpectedly.","solutions":["Record the Lock ID from the message and run terraform force-unlock <LOCK_ID>.","Verify the OTS table still exists and credentials retain tablestore:DeleteRow.","If the original failure was transient, re-run terraform init after force-unlock.","Audit for concurrent processes that removed the lock row out from under this run."],"exampleFix":"# the error prints:\n#   Error unlocking Alibaba Cloud OSS state file:\n#   Lock ID: 7e8f...\n# fix:\nterraform force-unlock 7e8f...","handlingStrategy":"fallback","validationCode":"// After a failed init, programmatically check for a dangling lock and offer force-unlock.\nfunc recoverInit(statePath string) error {\n    info, err := getLockInfo()\n    if err == nil && info.ID != \"\" {\n        fmt.Printf(\"dangling lock %s; run terraform force-unlock %s\\n\", info.ID, info.ID)\n    }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// Parse the Lock ID from the message and run force-unlock, then re-init.\nre := regexp.MustCompile(`Lock ID:\\s*([A-Za-z0-9-]+)`)\nif m := re.FindStringSubmatch(err.Error()); m != nil {\n    runForceUnlock(m[1])\n}","preventionTips":["Treat any failed init as potentially leaving a lock; always verify lock state after.","Give CI a cleanup step that force-unlocks the recorded lock ID on failure.","Investigate OTS availability if Unlock starts failing repeatedly."],"tags":["alibaba-cloud","tablestore","ots","remote-state","locking","force-unlock","go"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}