{"record":{"id":"262ca6059dee2718","repo":"hashicorp/terraform","slug":"listing-keys-for-s-v","errorCode":null,"errorMessage":"listing Keys for %s: %+v","messagePattern":"listing Keys for (.+?): %\\+v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/backend/remote-state/azure/storage_client_helpers.go","lineNumber":66,"sourceCode":"\t// primaryQueueEndpoint is the Primary Queue Endpoint for the Data Plane API for this Storage Account\n\t// e.g. `https://{account}.queue.core.windows.net`\n\tprimaryQueueEndpoint *string\n\n\t// primaryTableEndpoint is the Primary Table Endpoint for the Data Plane API for this Storage Account\n\t// e.g. `https://{account}.table.core.windows.net`\n\tprimaryTableEndpoint *string\n}\n\nfunc (ad *AccountDetails) AccountKey(ctx context.Context, client *storageaccounts.StorageAccountsClient) (*string, error) {\n\tif ad.accountKey != nil {\n\t\treturn ad.accountKey, nil\n\t}\n\n\topts := storageaccounts.DefaultListKeysOperationOptions()\n\topts.Expand = pointer.To(storageaccounts.ListKeyExpandKerb)\n\tlistKeysResp, err := client.ListKeys(ctx, ad.StorageAccountId, opts)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"listing Keys for %s: %+v\", ad.StorageAccountId, err)\n\t}\n\n\tif model := listKeysResp.Model; model != nil && model.Keys != nil {\n\t\tfor _, key := range *model.Keys {\n\t\t\tif key.Permissions == nil || key.Value == nil {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif *key.Permissions == storageaccounts.KeyPermissionFull {\n\t\t\t\tad.accountKey = key.Value\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tif ad.accountKey == nil {\n\t\treturn nil, fmt.Errorf(\"unable to determine the Write Key for %s\", ad.StorageAccountId)\n\t}","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/hashicorp/terraform/blob/c9def3e214014c1188faabfc4a5bde5095139765/internal/backend/remote-state/azure/storage_client_helpers.go#L48-L84","documentation":"AccountDetails.AccountKey (storage_client_helpers.go:66) calls the Azure Resource Manager `storageAccounts/ListKeys` operation (with Kerb expand) to fetch a storage account key for data-plane access. If the ARM call fails, the underlying error (permissions, throttling, connectivity, account not found) is wrapped via %+v.","triggerScenarios":"The azurerm remote backend, using access-key-based data-plane auth, lists keys for the configured storage_account_name/resource_group_name when the authenticated identity lacks `Microsoft.Storage/storageAccounts/listKeys/action`, the account does not exist, ARM throttled (429), or the network to management.azure.com is unreachable.","commonSituations":"Service principal without Storage Account Key Operator Service Role / Storage Account Contributor; wrong subscription or resource group; transient ARM 429/5xx; egress/firewall blocking the ARM endpoint.","solutions":["Grant the principal the Storage Account Key Operator Service Role (or Storage Account Contributor) on the target account.","Verify storage_account_name and resource_group_name reference an existing account.","Retry on 429/5xx; for persistent failures inspect the wrapped ARM error text.","Confirm network/egress to management.azure.com is allowed."],"exampleFix":"# before: principal has only Reader on the storage account\n# after: assign the key-listing role\naz role assignment create \\\n  --assignee <principal-id> \\\n  --role \"Storage Account Key Operator Service Role\" \\\n  --scope \"/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<acct>\"","handlingStrategy":"retry","validationCode":"# confirm the identity can list keys before terraform init\naz role assignment list --assignee <principal-id> \\\n  --scope \"/subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<acct>\" \\\n  --query \"[].roleDefinitionName\" --output tsv | grep -qi \"key operator\\|storage account contributor\" \\\n  || echo \"WARN: principal may lack listKeys permission\"","typeGuard":"// narrow a ListKeys error to decide retry vs abort\nfunc isTransientListKeysErr(err error) bool {\n    var rerr interface{ StatusCode() int }\n    if errors.As(err, &rerr) {\n        switch rerr.StatusCode() {\n        case 408, 429, 500, 502, 503, 504:\n            return true\n        }\n    }\n    return false\n}","tryCatchPattern":"// backoff/retry ListKeys for transient ARM failures, surface the rest\nvar key *string\nerr := backoff.Retry(func() error {\n    k, e := ad.AccountKey(ctx, keysClient)\n    if e != nil && isTransientListKeysErr(e) {\n        return e\n    }\n    key = k\n    return e\n}, backoff.NewExponentialBackOff())","preventionTips":["Grant the principal the Storage Account Key Operator Service Role on the account.","Allow egress to management.azure.com from the terraform runtime.","Treat 429/5xx as transient with backoff; treat 403 as a permission failure."],"tags":["azure","storage","arm","permissions","network","authentication"],"analyzedSha":"c9def3e214014c1188faabfc4a5bde5095139765","analyzedAt":"2026-08-07T15:39:49.278Z","schemaVersion":2},"datasetVersion":"2026-08-07T20:17:04.800Z"}