hashicorp/terraform · error
Failed to retrieve lock information from OCI Object Storage:
Error message
Failed to retrieve lock information from OCI Object Storage: %w
What it means
Raised in Unlock as the outer wrap over any failure returned by getLockInfo (errors 307/308/309). Unlock must read and parse the existing lock file before it can verify the ID and issue the conditional DeleteObject, so any failure to retrieve or parse lock information surfaces through this message.
Source
Thrown at internal/backend/remote-state/oci/client.go:331
}
lockByteData, err := io.ReadAll(getResponse.Content)
if err != nil {
return nil, *getResponse.ETag, fmt.Errorf("failed to read existing lock file content: %w", err)
}
lockInfo := &statemgr.LockInfo{}
if err := json.Unmarshal(lockByteData, lockInfo); err != nil {
return lockInfo, "", fmt.Errorf("failed to unmarshal JSON data into LockInfo struct: %w", err)
}
return lockInfo, *getResponse.ETag, nil
}
func (c *RemoteClient) Unlock(id string) error {
ctx := context.TODO()
logger := logWithOperation("unlock-state-file").Named(c.lockFilePath)
logger.Info("unlocking remote state")
lockInfo, etag, err := c.getLockInfo(ctx)
if err != nil {
return fmt.Errorf("Failed to retrieve lock information from OCI Object Storage: %w", err)
}
// Verify that the provided lock ID matches the lock ID of the retrieved lock file.
if lockInfo.ID != id {
return &statemgr.LockError{
Info: lockInfo,
Err: fmt.Errorf("lock ID '%s' does not match the existing lock ID '%s'", id, lockInfo.ID),
}
}
deleteRequest := objectstorage.DeleteObjectRequest{
NamespaceName: common.String(c.namespace),
ObjectName: common.String(c.lockFilePath),
BucketName: common.String(c.bucketName),
IfMatch: common.String(etag),
RequestMetadata: common.RequestMetadata{
RetryPolicy: getDefaultRetryPolicy(),
},
}View on GitHub (pinned to c9def3e214)
Solutions
- Unwrap the error to see whether it is 307 (get), 308 (read), or 309 (unmarshal) and follow that sub-error's fix.
- For a missing lock file (404 under the wrap), the lock is already gone — verify with 'oci os object list --prefix <lockfile>' and clear any stale local state.
- For a corrupt lock file, follow the unmarshal fix: inspect/delete the lock object once you confirm no real holder exists.
- Re-run the unlock after fixing the underlying read/parse issue.
Defensive patterns
Strategy: retry
Validate before calling
// Probe lock file presence before attempting a full Unlock: // oci os object head --namespace <ns> --bucket-name <b> --name <lockfile> // If absent, skip Unlock (nothing to release).
Type guard
// Unwrap to find the specific sub-cause (307/308/309):
var se common.ServiceError
if errors.As(err, &se) && se.GetHTTPStatusCode() == 404 { /* no lock -> already unlocked */ } Try / catch
lockInfo, etag, err := c.getLockInfo(ctx)
if err != nil {
return fmt.Errorf("Failed to retrieve lock information from OCI Object Storage: %w", err)
} Prevention
- Before unlock, confirm a lock file actually exists.
- Fix the underlying read/parse issue (307/308/309) first.
- Retry transient retrieval failures.
When it happens
Trigger: Unlock calls getLockInfo (client.go:328) which returns a non-nil error: GetObject fails (307), body read fails (308), or JSON unmarshal fails (309). The wrapped %w carries the specific sub-cause.
Common situations: Running 'terraform force-unlock'/'terraform unlock' when the lock file is missing, unreadable, or corrupt; IAM lacking read on the bucket at unlock time; transient read/parse failure.
Related errors
- failed to read existing lock file content: %w
- failed to unmarshal JSON data into LockInfo struct: %w
- lock ID '%s' does not match the existing lock ID '%s'
- failed to access object '%s' in bucket '%s': %w
- failed to access object HttpStatusCode: %d OpcRequestId: %s
AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07).
Data as JSON: /api/errors/6bbc6e2a9a55006a.
Report an issue: GitHub.