{"record":{"id":"8603260a6b4461a8","repo":"hashicorp/terraform","slug":"failed-to-retrieve-lock-info-s","errorCode":null,"errorMessage":"failed to retrieve lock info: %s","messagePattern":"failed to retrieve lock info: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/azure/client.go","lineNumber":277,"sourceCode":"\t\tvalue := base64.StdEncoding.EncodeToString(info.Marshal())\n\t\tblob.MetaData[lockInfoMetaKey] = value\n\t}\n\n\topts := blobs.SetMetaDataInput{\n\t\tLeaseID:  &c.leaseID,\n\t\tMetaData: blob.MetaData,\n\t}\n\n\t_, err = c.giovanniBlobClient.SetMetaData(ctx, c.containerName, c.keyName, opts)\n\treturn err\n}\n\nfunc (c *RemoteClient) Unlock(id string) error {\n\tlockErr := &statemgr.LockError{}\n\n\tlockInfo, err := c.getLockInfo()\n\tif err != nil {\n\t\tlockErr.Err = fmt.Errorf(\"failed to retrieve lock info: %s\", err)\n\t\treturn lockErr\n\t}\n\tlockErr.Info = lockInfo\n\n\tif lockInfo.ID != id {\n\t\tlockErr.Err = fmt.Errorf(\"lock id %q does not match existing lock\", id)\n\t\treturn lockErr\n\t}\n\n\tc.leaseID = lockInfo.ID\n\tif err := c.writeLockInfo(nil); err != nil {\n\t\tlockErr.Err = fmt.Errorf(\"failed to delete lock info from metadata: %s\", err)\n\t\treturn lockErr\n\t}\n\n\tctx := newCtx()\n\t_, err = c.giovanniBlobClient.ReleaseLease(ctx, c.containerName, c.keyName, blobs.ReleaseLeaseInput{LeaseID: id})\n\tif err != nil {","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/hashicorp/terraform/blob/d32a084675427f5ac3f7d2868578ef8b2c1dc525/internal/backend/remote-state/azure/client.go#L259-L295","documentation":"Returned by RemoteClient.Unlock when c.getLockInfo() fails. Wraps either error 158 (empty terraformlockid metadata) or any failure from the underlying GetProperties call (network, RBAC, blob deleted). Returned as a statemgr.LockError so terraform surfaces it appropriately during `terraform force-unlock` or automatic unlock.","triggerScenarios":"(a) Same as 158 (metadata empty/missing). (b) GetProperties failed: network, identity lost Read on the blob, account throttled. (c) Blob was deleted before the unlock call.","commonSituations":"Permissions revoked mid-run; state blob force-deleted while a lock is held; flaky network during force-unlock; manual lease break left the metadata inconsistent.","solutions":["Break the lease manually via `az storage blob lease break` to bypass Terraform's metadata-based unlock.","Verify the identity can read blob metadata (Storage Blob Data Reader minimum).","If the blob was deleted, no unlock is needed — recreate the workspace state.","Retry `terraform force-unlock` after fixing permissions/network."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Pre-flight: confirm the identity can read blob metadata before attempting unlock.\nfunc canReadBlobMetadata(ctx context.Context, acct, container, blob string) error {\n    cmd := exec.CommandContext(ctx, \"az\", \"storage\", \"blob\", \"show\",\n        \"--account-name\", acct, \"-c\", container, \"-n\", blob, \"--query\", \"metadata\", \"-o\", \"json\")\n    if _, err := cmd.Output(); err != nil { return fmt.Errorf(\"cannot read blob metadata: %w\", err) }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"// On Unlock failure, fall back to a manual lease break and report.\nif err := client.Unlock(id); err != nil {\n    var le *statemgr.LockError\n    if errors.As(err, &le) {\n        log.Printf(\"unlock failed (%v); break lease manually: az storage blob lease break --account-name %s -c %s -b %s\",\n            le.Err, acct, container, blob)\n    }\n}","preventionTips":["Maintain Storage Blob Data Reader/Contributor on the state blob throughout the run; do not revoke mid-operation.","Do not delete the state blob while a lock is held.","Provide a runbook that includes `az storage blob lease break` as the recovery primitive when force-unlock fails."],"tags":["azure","state-locking","lease","force-unlock","metadata","wrapper"],"backgroundTag":null,"analyzedSha":"d32a084675427f5ac3f7d2868578ef8b2c1dc525","analyzedAt":"2026-08-11T18:43:52.779Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}