{"record":{"id":"5a25850c10d266cb","repo":"hashicorp/terraform","slug":"lock-file-s-exists","errorCode":null,"errorMessage":"lock file %s exists","messagePattern":"lock file (.+?) exists","errorType":"console","errorClass":"statemgr.LockError","httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/cos/client.go","lineNumber":98,"sourceCode":"}\n\n// Lock lock remote state file for writing\nfunc (c *remoteClient) Lock(info *statemgr.LockInfo) (string, error) {\n\tlog.Printf(\"[DEBUG] lock remote state file %s\", c.lockFile)\n\n\terr := c.cosLock(c.bucket, c.lockFile)\n\tif err != nil {\n\t\treturn \"\", c.lockError(err)\n\t}\n\tdefer c.cosUnlock(c.bucket, c.lockFile)\n\n\texists, _, _, err := c.getObject(c.lockFile)\n\tif err != nil {\n\t\treturn \"\", c.lockError(err)\n\t}\n\n\tif exists {\n\t\treturn \"\", c.lockError(fmt.Errorf(\"lock file %s exists\", c.lockFile))\n\t}\n\n\tinfo.Path = c.lockFile\n\tdata, err := json.Marshal(info)\n\tif err != nil {\n\t\treturn \"\", c.lockError(err)\n\t}\n\n\tcheck := fmt.Sprintf(\"%x\", md5.Sum(data))\n\terr = c.putObject(c.lockFile, data)\n\tif err != nil {\n\t\treturn \"\", c.lockError(err)\n\t}\n\n\treturn check, nil\n}\n\n// Unlock unlock remote state file","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/cos/client.go#L80-L116","documentation":"Raised by remoteClient.Lock() (cos/client.go:98) after the COS tag lock is acquired. Lock() then checks whether the lock file object already exists in the bucket; if it does, another Terraform run already holds the state lock, so this run must abort and release its tag lock.","triggerScenarios":"Lock() calls getObject(c.lockFile) and exists==true, meaning the <state>.tflock object is present from a prior/active lock holder.","commonSituations":"Concurrent terraform runs on the same workspace; a previous run crashed and left the lock file object behind; a force-unlock was not performed after a crash.","solutions":["Wait for the other terraform run to finish and release the lock, then retry.","If the holder is gone, run `terraform force-unlock <lock-id>` to remove the stale lock file.","As a last resort, delete the lock file object and the tencentcloud-terraform-lock tag in the COS console, then retry."],"exampleFix":"// after 'lock file ... exists'\nterraform force-unlock <lock-id>\nterraform apply","handlingStrategy":"retry","validationCode":"// Pre-check whether a lock file already exists before attempting Lock\nfunc alreadyLocked(c *remoteClient) bool {\n    exists, _, _, _ := c.getObject(c.lockFile)\n    return exists\n}","typeGuard":null,"tryCatchPattern":"// Retry Lock when contention is transient; force-unlock if stale\nfor attempt := 0; attempt < 3; attempt++ {\n    _, err := c.Lock(info)\n    if err == nil { break }\n    if !strings.Contains(err.Error(), \"lock file\") { return err }\n    time.Sleep(time.Duration(attempt+1) * 2 * time.Second)\n}","preventionTips":["Serialize terraform runs per workspace to avoid lock contention.","Clear stale lock files with `terraform force-unlock` after crashes.","Never delete the lock file manually unless force-unlock fails."],"tags":["cos","tencentcloud","lock","concurrency","lock-file","workspace"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}