hashicorp/terraform · error
failed to retrieve lock info
Error message
failed to retrieve lock info: %s
What it means
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.
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.
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-flight: confirm the identity can read blob metadata before attempting unlock.
func canReadBlobMetadata(ctx context.Context, acct, container, blob string) error {
cmd := exec.CommandContext(ctx, "az", "storage", "blob", "show",
"--account-name", acct, "-c", container, "-n", blob, "--query", "metadata", "-o", "json")
if _, err := cmd.Output(); err != nil { return fmt.Errorf("cannot read blob metadata: %w", err) }
return nil
} Try / catch
// On Unlock failure, fall back to a manual lease break and report.
if err := client.Unlock(id); err != nil {
var le *statemgr.LockError
if errors.As(err, &le) {
log.Printf("unlock failed (%v); break lease manually: az storage blob lease break --account-name %s -c %s -b %s",
le.Err, acct, container, blob)
}
} Prevention
- 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.
When it happens
Trigger: (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.
Common situations: 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.
Related errors
- blob metadata was empty
- Error unlocking Azure state. Lock ID
- state blob is already locked
- failed to lock azure state
- error snapshotting Blob
AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11).
Data as JSON: /api/errors/8603260a6b4461a8.
Report an issue: GitHub.
Appendix: source
Thrown at internal/backend/remote-state/azure/client.go:277
value := base64.StdEncoding.EncodeToString(info.Marshal())
blob.MetaData[lockInfoMetaKey] = value
}
opts := blobs.SetMetaDataInput{
LeaseID: &c.leaseID,
MetaData: blob.MetaData,
}
_, err = c.giovanniBlobClient.SetMetaData(ctx, c.containerName, c.keyName, opts)
return err
}
func (c *RemoteClient) Unlock(id string) error {
lockErr := &statemgr.LockError{}
lockInfo, err := c.getLockInfo()
if err != nil {
lockErr.Err = fmt.Errorf("failed to retrieve lock info: %s", err)
return lockErr
}
lockErr.Info = lockInfo
if lockInfo.ID != id {
lockErr.Err = fmt.Errorf("lock id %q does not match existing lock", id)
return lockErr
}
c.leaseID = lockInfo.ID
if err := c.writeLockInfo(nil); err != nil {
lockErr.Err = fmt.Errorf("failed to delete lock info from metadata: %s", err)
return lockErr
}
ctx := newCtx()
_, err = c.giovanniBlobClient.ReleaseLease(ctx, c.containerName, c.keyName, blobs.ReleaseLeaseInput{LeaseID: id})
if err != nil {View on GitHub (pinned to d32a084675)