{"record":{"id":"e4805fb081976b4c","repo":"hashicorp/terraform","slug":"failed-to-lock-inmem-state-s","errorCode":null,"errorMessage":"failed to lock inmem state: %s","messagePattern":"failed to lock inmem state: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/inmem/backend.go","lineNumber":147,"sourceCode":"\tstates.Lock()\n\tdefer states.Unlock()\n\n\ts := states.m[name]\n\tif s == nil {\n\t\ts = &remote.State{\n\t\t\tClient: &RemoteClient{\n\t\t\t\tName: name,\n\t\t\t},\n\t\t}\n\t\tstates.m[name] = s\n\n\t\t// to most closely replicate other implementations, we are going to\n\t\t// take a lock and create a new state if it doesn't exist.\n\t\tlockInfo := statemgr.NewLockInfo()\n\t\tlockInfo.Operation = \"init\"\n\t\tlockID, err := s.Lock(lockInfo)\n\t\tif err != nil {\n\t\t\treturn nil, diags.Append(fmt.Errorf(\"failed to lock inmem state: %s\", err))\n\t\t}\n\t\tdefer s.Unlock(lockID)\n\n\t\t// If we have no state, we have to create an empty state\n\t\tif v := s.State(); v == nil {\n\t\t\tif err := s.WriteState(statespkg.NewState()); err != nil {\n\t\t\t\treturn nil, diags.Append(err)\n\t\t\t}\n\t\t\tif err := s.PersistState(nil); err != nil {\n\t\t\t\treturn nil, diags.Append(err)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn s, diags\n}\n\ntype stateMap struct {","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/remote-state/inmem/backend.go#L129-L165","documentation":"Thrown during inmem StateMgr initialization when acquiring the initial lock on a freshly created state fails (backend.go:144-148). The inmem backend takes a lock (lockInfo.Operation = \"init\") to replicate other backends; if s.Lock returns an error, the StateMgr cannot be set up. The %s is the lock error.","triggerScenarios":"The in-memory lock on the named workspace is already held by another goroutine when StateMgr(name) tries to lock it for init. Inmem uses an in-process lock, so this requires concurrent access within the same process.","commonSituations":"Concurrent tests in the same process racing on the same inmem workspace; a previous operation that failed to release its lock; a deadlock in test teardown leaving the lock held.","solutions":["Ensure only one goroutine accesses a given inmem workspace at a time.","Guarantee prior operations call Unlock even on error paths (proper defer/cleanup).","In tests, use distinct workspace names per parallel test or serialize access.","Recreate the inmem backend between tests to start with a clean lock table."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// _, diags := b.StateMgr(name)\n// for _, d := range diags {\n//   if strings.Contains(d.Description().Summary, \"failed to lock inmem state\") {\n//     // in-process contention; serialize access or recreate the backend\n//   }\n// }","preventionTips":["Serialize goroutine access to a single inmem workspace.","Always defer Unlock after Lock, including on error paths.","Recreate the inmem backend between tests for a clean lock table."],"tags":["inmem-backend","locking","concurrency","init"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}