{"record":{"id":"2821712689c5e623","repo":"hashicorp/terraform","slug":"lock-id-q-does-not-match-existing-lock-id-s-s-282171","errorCode":null,"errorMessage":"lock ID %q does not match existing lock ID \"%s/%s\"","messagePattern":"lock ID %q does not match existing lock ID \"(.+?)/(.+?)\"","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cloud/state.go","lineNumber":503,"sourceCode":"\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t\t// This will not be retried\n\t\t\t\treturn &errorUnlockFailed{innerError: err}\n\t\t\t}\n\t\t\treturn nil\n\t\t})\n\n\t\tif err != nil {\n\t\t\tlockErr.Err = err\n\t\t\treturn lockErr\n\t\t}\n\n\t\treturn nil\n\t}\n\n\t// Verify the optional force-unlock lock ID.\n\tif s.organization+\"/\"+s.workspace.Name != id {\n\t\tlockErr.Err = fmt.Errorf(\n\t\t\t\"lock ID %q does not match existing lock ID \\\"%s/%s\\\"\",\n\t\t\tid,\n\t\t\ts.organization,\n\t\t\ts.workspace.Name,\n\t\t)\n\t\treturn lockErr\n\t}\n\n\t// Force unlock the workspace.\n\t_, err := s.tfeClient.Workspaces.ForceUnlock(ctx, s.workspace.ID)\n\tif err != nil {\n\t\tlockErr.Err = err\n\t\treturn lockErr\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/cloud/state.go#L485-L521","documentation":"Thrown during Unlock when s.lockInfo is nil (no normal lock was held, implying a force-unlock attempt) but the caller-supplied id does not match the expected org/workspace format (organization/workspaceName). This validates that the caller is intentionally force-unlocking the correct workspace before calling Workspaces.ForceUnlock.","triggerScenarios":"Force-unlock attempted with an ID that does not match the \"organization/workspaceName\" pattern; s.lockInfo was cleared or never set but Unlock is called with a leftover normal-lock ID; misconfigured state manager that skipped the Lock phase but still tries to Unlock.","commonSituations":"Programmatic usage of the cloud State type outside the normal statemgr lifecycle; a state manager reused after a failed initialization; testing code that constructs State manually without going through the backend factory.","solutions":["When force-unlocking, pass the ID in the exact format \"organization/workspaceName\"","Ensure Lock is called before Unlock in the normal flow so s.lockInfo is populated","If using the terraform CLI, use 'terraform force-unlock <LOCK_ID>' which formats the ID correctly"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// For force-unlock, construct the expected ID and validate it:\nexpectedID := organization + \"/\" + workspaceName\nif forceUnlockID != expectedID {\n    return fmt.Errorf(\"force-unlock ID must be %q, got %q\", expectedID, forceUnlockID)\n}","typeGuard":null,"tryCatchPattern":"err := stateMgr.Unlock(id)\nif err != nil && strings.Contains(err.Error(), \"does not match existing lock ID\") {\n    // force-unlock ID format is wrong; inform user of the expected format\n    return fmt.Errorf(\"use lock ID %q for force-unlock of %s/%s\", org+\"/\"+ws, org, ws)\n}\nreturn err","preventionTips":["For force-unlock via the cloud State type, always use the 'organization/workspaceName' format","Prefer the terraform CLI 'terraform force-unlock' command which formats IDs correctly","Do not mix normal-lock IDs with force-unlock IDs in the same code path"],"tags":["locking","force-unlock","state-unlock","tfe","terraform"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}