{"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/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/inmem/backend.go#L129-L165","documentation":"When the in-memory backend initializes a brand-new state for a workspace it lazily acquires an init lock via s.Lock(); if that lock call fails (e.g. another holder already locked it), the wrapped error is surfaced here. This protects against two writers creating the initial empty state concurrently.","triggerScenarios":"Calling StateMgr(name) for a workspace that has no state yet (inmem/backend.go:132-159), where stateMgr.Lock returns an error because the global locks map already holds a lock for that name (set, for example, via the lock_id config attribute).","commonSituations":"A backend configured with `lock_id` in a test that pre-locks the default state, then StateMgr is called and the init lock conflicts with that pre-existing lock; concurrent test setup racing to initialize the same workspace; a stale lock left behind by a crashed test that was never Reset().","solutions":["Call inmem.Reset() between tests to clear stale locks and states.","If using the lock_id config intentionally, ensure the workspace whose state you request is not the one pre-locked, or unlock it first.","Serialize test setup so only one writer initializes a given workspace at a time."],"exampleFix":"// before - each test leaves locks behind, next StateMgr() fails\nterraform.Init(ctx)\n\n// after - reset in-memory state (and locks) between tests\ninmem.Reset()\nterraform.Init(ctx)","handlingStrategy":"validation","validationCode":"// Ensure no pre-existing lock for the workspace before requesting a new state mgr\nstates.Lock(); defer states.Unlock()\nif _, locked := locks.m[name]; locked {\n    // clear stale test lock or fail fast with a clear message\n    delete(locks.m, name)\n}\ns, diags := b.StateMgr(name)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call inmem.Reset() in test SetUp/TearDown to clear locks and states.","Do not set lock_id on a workspace you then immediately initialize via StateMgr.","Serialize concurrent initializations of the same inmem workspace."],"tags":["inmem","remote-state","locking","terraform-backend","testing"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T21:17:07.882Z"}