How to Troubleshoot Azure Cost Management Export Issues
Azure Cost Management exports are critical for automated billing analysis, but they can fail for various reasons—from permission issues to storage configuration problems. This guide provides systematic troubleshooting steps to diagnose and resolve the most common export issues, helping you maintain reliable cost data pipelines.
Prerequisites
Before troubleshooting, ensure you have:
- Access to Azure portal with appropriate permissions (Cost Management Reader or higher)
- Export configuration details (schedule name, storage account, container path)
- Azure CLI or PowerShell installed (for advanced diagnostics)
- Storage account access where exports are configured to write
- Understanding of your export configuration (daily/monthly, scope, date range)
Understanding Azure Cost Management Exports
Cost Management exports automate the delivery of cost and usage data to Azure Storage. Key components:
- Export schedule: Defines frequency (daily, weekly, monthly)
- Scope: Subscription, Resource Group, Management Group, or Billing Account
- Date range: Month-to-date, custom date range, or full history
- Destination: Azure Storage account, container, and path
- File format: CSV or Parquet
- Permissions: Managed identity or manual RBAC assignments
Common Export Issues and Solutions
Issue 1: Export Never Runs or No Files Created
Symptoms:
- Export shows "Created" status but never runs
- No files appear in storage account
- Export history shows no runs
Common Causes:
- Missing permissions on storage account
- Export not yet scheduled to run
- Storage account behind firewall/private endpoint
- Invalid storage path configuration
Solutions:
Step 1: Verify Export Schedule
# Check export configuration using Azure CLI
az costmanagement export show \
--name "MyDailyCostExport" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID"
# Look for:
# - schedule.status: "Active"
# - schedule.recurrence: "Daily"
# - deliveryInfo.destination.container: correct name
Step 2: Check Storage Account Permissions
# List role assignments on storage account
az role assignment list \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID/resourceGroups/YOUR_RG/providers/Microsoft.Storage/storageAccounts/YOUR_STORAGE" \
--output table
# Export needs "Storage Blob Data Contributor" role
# If missing, grant it:
az role assignment create \
--role "Storage Blob Data Contributor" \
--assignee-object-id "YOUR_EXPORT_MANAGED_IDENTITY_ID" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID/resourceGroups/YOUR_RG/providers/Microsoft.Storage/storageAccounts/YOUR_STORAGE"
Step 3: Verify Storage Account Network Access
- Go to Azure Portal > Storage Account > Networking
- Check if "Enabled from selected virtual networks and IP addresses" is selected
- If yes, add exception: "Allow Azure services on the trusted services list to access this storage account"
- Alternative: Add Cost Management service to allowed services
Step 4: Test Manual Run
# Trigger one-time export execution
az costmanagement export create \
--name "TestExport" \
--type "Usage" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID" \
--storage-account-id "/subscriptions/YOUR_SUBSCRIPTION_ID/resourceGroups/YOUR_RG/providers/Microsoft.Storage/storageAccounts/YOUR_STORAGE" \
--storage-container "costexports" \
--timeframe "MonthToDate"
Issue 2: Export Fails with Permission Errors
Symptoms:
- Export history shows "Failed" status
- Error message: "The export does not have permission to write to the destination"
- Error code:
ExportFailedPermissionDenied
Solutions:
Step 1: Verify Managed Identity (If Used)
# Check if export has managed identity
az costmanagement export show \
--name "MyExport" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID" \
--query "identity"
# If using managed identity, ensure it has Storage Blob Data Contributor
# Get the managed identity principal ID from output above
Step 2: Grant Required RBAC Roles
Navigate to Storage Account in Azure Portal:
- Go to Access Control (IAM) > Add role assignment
- Select role: Storage Blob Data Contributor
- Assign access to: Managed identity or User, group, or service principal
- Select: The export's managed identity or Cost Management service principal
- Click Save
Step 3: Check Storage Account Hierarchical Namespace
If using Azure Data Lake Storage Gen2:
# Verify if hierarchical namespace is enabled
az storage account show \
--name "YOUR_STORAGE" \
--resource-group "YOUR_RG" \
--query "isHnsEnabled"
# If true, also grant "Storage Blob Data Contributor" at container level
Step 4: Verify No Conflicting Deny Assignments
# Check for Azure Policy deny assignments
az policy assignment list \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID" \
--query "[?contains(displayName, 'Storage') || contains(displayName, 'Blob')]"
# Review any policies that might block write access
Issue 3: Export Files Are Empty or Incomplete
Symptoms:
- Files appear in storage but contain no data or only headers
- File size is abnormally small (< 1 KB)
- CSV has headers but no rows
Solutions:
Step 1: Verify Scope Has Billable Resources
# Check if scope has any cost data
az costmanagement query \
--type "Usage" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID" \
--timeframe "MonthToDate" \
--dataset-aggregation '{"totalCost":{"name":"Cost","function":"Sum"}}' \
--dataset-grouping name="ResourceGroup" type="Dimension"
# If query returns no data, scope has no costs to export
Step 2: Check Date Range Configuration
- Go to Cost Management > Exports > Select your export
- Verify "Date range" setting:
- Month-to-date: Only current month data
- Custom date range: Check start/end dates are valid
- Last month: Previous month only
- If using custom dates, ensure range overlaps with actual resource usage
Step 3: Verify Export Type Matches Available Data
- Actual Cost: Current charges (use this for most scenarios)
- Amortized Cost: Spreads reservation costs over time
- Usage: Raw usage data without pricing
- Some scopes may not have data for all types
Step 4: Check for Filtering Issues
# Review export definition for filters
az costmanagement export show \
--name "MyExport" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID" \
--query "definition.dataSet.filter"
# Overly restrictive filters may exclude all data
Issue 4: Export Runs But Files Missing from Expected Location
Symptoms:
- Export history shows "Completed" status
- Files not in configured container/path
- Files appear in unexpected location
Solutions:
Step 1: Verify Storage Path Configuration
# Check exact path configuration
az costmanagement export show \
--name "MyExport" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID" \
--query "deliveryInfo.destination"
# Output shows:
# - container: "costexports"
# - rootFolderPath: "reports/daily"
Step 2: Understand Default Naming Convention
Azure creates files with pattern:
{container}/{rootFolderPath}/{exportName}/{yyyyMMdd-yyyyMMdd}/{exportName}_{guid}.csv
Example:
costexports/reports/daily/DailyCostExport/20250101-20250131/DailyCostExport_12345678-90ab-cdef.csv
Step 3: Search All Containers
# List all containers in storage account
az storage container list \
--account-name "YOUR_STORAGE" \
--output table
# Search for recent files
az storage blob list \
--container-name "costexports" \
--account-name "YOUR_STORAGE" \
--output table \
--query "sort_by([?properties.lastModified >= '2025-01-01'], &properties.lastModified)"
Step 4: Check for Multiple Exports Writing to Same Path
- Multiple exports with same rootFolderPath can cause confusion
- Review all exports and ensure unique paths
Issue 5: Export Stops Running After Working Previously
Symptoms:
- Export worked for weeks/months, then suddenly stops
- Last successful run was days/weeks ago
- No recent changes to configuration
Common Causes:
- Storage account key rotation
- Managed identity disabled or deleted
- Storage account moved/renamed
- Expired credentials (if using service principal)
- Subscription disabled/expired
Solutions:
Step 1: Check Storage Account Status
# Verify storage account exists and is accessible
az storage account show \
--name "YOUR_STORAGE" \
--resource-group "YOUR_RG"
# Check provisioning state should be "Succeeded"
Step 2: Re-validate Permissions
# Re-check role assignments (may have been removed)
az role assignment list \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID/resourceGroups/YOUR_RG/providers/Microsoft.Storage/storageAccounts/YOUR_STORAGE" \
--all
# If missing, re-grant Storage Blob Data Contributor
Step 3: Recreate Export
If all else fails, delete and recreate export:
# Export current configuration first
az costmanagement export show \
--name "MyExport" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID" > export-backup.json
# Delete export
az costmanagement export delete \
--name "MyExport" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID"
# Recreate with same settings (using Azure Portal for easier setup)
Issue 6: Export Runs Daily But Contains Old Data
Symptoms:
- Files created daily as scheduled
- Data inside is days/weeks old
- Missing recent cost data
Solutions:
Step 1: Understand Data Latency
Azure Cost Management data has inherent latency:
- Consumption data: 24-48 hours delay
- Marketplace charges: Up to 72 hours
- Azure Hybrid Benefit: Can take 48+ hours
- Reservation purchases: Immediate, but amortization takes time
This is normal—don't expect same-day cost data.
Step 2: Verify Date Range Configuration
# Check if using "MonthToDate" or fixed date range
az costmanagement export show \
--name "MyExport" \
--scope "/subscriptions/YOUR_SUBSCRIPTION_ID" \
--query "definition.timeframe"
# "MonthToDate" should include current month up to yesterday
# Fixed date ranges don't move forward
Step 3: Check for Overwrite vs. Create New
- Verify if export is configured to overwrite existing files
- If overwriting, file might show old timestamp but have new data
- Check file contents, not just modification date
Issue 7: Large Exports Fail or Time Out
Symptoms:
- Export fails with timeout error
- Works for small scopes but fails for large ones
- Error: "Export execution exceeded time limit"
Solutions:
Step 1: Split Export by Scope
Instead of exporting entire billing account, create separate exports:
# Create per-subscription exports
for sub in $(az account list --query "[].id" -o tsv); do
az costmanagement export create \
--name "Export-${sub:0:8}" \
--scope "/subscriptions/$sub" \
--storage-account-id "YOUR_STORAGE_ACCOUNT_ID" \
--storage-container "costexports" \
--storage-directory "$sub" \
--timeframe "MonthToDate" \
--type "ActualCost" \
--schedule-status "Active" \
--schedule-recurrence "Daily"
done
Step 2: Use Parquet Format (More Efficient)
- Parquet compresses better and transfers faster
- Configure export to use Parquet instead of CSV
- Azure Portal > Cost Management > Exports > Create/Edit > File format: Parquet
Step 3: Reduce Date Range
- Use "MonthToDate" instead of custom 12-month range
- Create separate exports for historical vs. current data
- Historical: One-time export for past 12 months
- Current: Daily/weekly export for current month
Step 4: Increase Timeout (If Using API)
# Python example with increased timeout
from azure.identity import DefaultAzureCredential
from azure.mgmt.costmanagement import CostManagementClient
credential = DefaultAzureCredential()
client = CostManagementClient(credential, timeout=600) # 10 minutes
Advanced Diagnostics
Enable Diagnostic Logging for Storage Account
# Create Log Analytics workspace
az monitor log-analytics workspace create \
--resource-group "YOUR_RG" \
--workspace-name "storage-diagnostics"
# Enable storage account diagnostic logs
az monitor diagnostic-settings create \
--resource "/subscriptions/YOUR_SUBSCRIPTION_ID/resourceGroups/YOUR_RG/providers/Microsoft.Storage/storageAccounts/YOUR_STORAGE" \
--name "export-diagnostics" \
--logs '[{"category":"StorageWrite","enabled":true}]' \
--workspace "storage-diagnostics"
# Query logs after next export attempt
Check Azure Service Health
# Check for Azure platform issues
az rest --method get \
--url "https://management.azure.com/subscriptions/YOUR_SUBSCRIPTION_ID/providers/Microsoft.ResourceHealth/availabilityStatuses?api-version=2020-05-01" \
--query "value[?properties.reasonChronicity == 'Persistent']"
# Visit Azure Status page: https://status.azure.com
Review Export Execution History Programmatically
# PowerShell: Get detailed export run history
$scope = "/subscriptions/YOUR_SUBSCRIPTION_ID"
$exportName = "MyExport"
$runs = Get-AzCostManagementExportExecutionHistory -Scope $scope -ExportName $exportName
$runs | Select-Object ExecutionType, Status, SubmittedTime, ProcessingStartTime, ProcessingEndTime, FileName | Format-Table
# Investigate failed runs
$failedRuns = $runs | Where-Object { $_.Status -eq "Failed" }
$failedRuns | Select-Object Status, Error
Best Practices to Prevent Issues
1. Use Managed Identity (Recommended)
- More secure than storage account keys
- No credential expiration
- Automatic rotation
Configuration:
- Create export with managed identity enabled
- Grant Storage Blob Data Contributor to the managed identity
- No need to manage secrets
2. Implement Monitoring and Alerting
Create alert for export failures:
# Azure CLI: Create alert rule for failed exports
az monitor metrics alert create \
--name "CostExportFailureAlert" \
--resource-group "YOUR_RG" \
--scopes "/subscriptions/YOUR_SUBSCRIPTION_ID" \
--condition "count > 0" \
--window-size 1d \
--evaluation-frequency 1h \
--description "Alert when cost export fails"
PowerShell: Monitor export status:
# Check export status daily
$scope = "/subscriptions/YOUR_SUBSCRIPTION_ID"
$export = Get-AzCostManagementExport -Scope $scope -ExportName "DailyCostExport"
if ($export.Schedule.Status -ne "Active") {
Send-MailMessage -To "[email protected]" -Subject "Export Inactive" -Body "Export status: $($export.Schedule.Status)"
}
3. Implement Redundancy
Create backup export to secondary storage:
# Primary export to main storage
az costmanagement export create --name "Primary-Export" ...
# Backup export to secondary storage account
az costmanagement export create --name "Backup-Export" \
--storage-account-id "/subscriptions/SUB_ID/resourceGroups/RG/providers/Microsoft.Storage/storageAccounts/BACKUP_STORAGE" ...
4. Document Export Configuration
Maintain documentation:
# export-config.yaml
exports:
- name: DailyCostExport
scope: /subscriptions/abc-123
schedule: Daily at 02:00 UTC
destination:
storage: costmgmtstorage
container: costexports
path: daily
format: CSV
type: ActualCost
managed_identity: /subscriptions/abc-123/resourceGroups/rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/export-identity
- name: MonthlyAmortizedExport
scope: /subscriptions/abc-123
schedule: Monthly on 1st at 04:00 UTC
destination:
storage: costmgmtstorage
container: costexports
path: monthly
format: Parquet
type: AmortizedCost
managed_identity: /subscriptions/abc-123/resourceGroups/rg/providers/Microsoft.ManagedIdentity/userAssignedIdentities/export-identity
5. Automate Export Validation
Python script to validate daily exports:
from azure.storage.blob import BlobServiceClient
from datetime import datetime, timedelta
import sys
# Configuration
storage_account = "costmgmtstorage"
container = "costexports"
connection_string = "DefaultEndpointsProtocol=https;..."
# Connect to storage
blob_service = BlobServiceClient.from_connection_string(connection_string)
container_client = blob_service.get_container_client(container)
# Check for today's export
today = datetime.now().strftime("%Y%m%d")
expected_prefix = f"daily/DailyCostExport/{today}"
blobs = list(container_client.list_blobs(name_starts_with=expected_prefix))
if not blobs:
print(f"ERROR: No export found for {today}")
sys.exit(1)
# Check file size
blob_size = blobs[0].size
if blob_size < 1024: # Less than 1 KB
print(f"WARNING: Export file unusually small: {blob_size} bytes")
sys.exit(1)
print(f"SUCCESS: Export found - {blobs[0].name} ({blob_size} bytes)")
Troubleshooting Checklist
Use this checklist when troubleshooting export issues:
- Export status is "Active" (not paused)
- Storage account exists and is accessible
- Storage Blob Data Contributor role assigned to export identity
- Storage account firewall allows Cost Management service
- Container name is correct (case-sensitive)
- Root folder path is valid (no leading/trailing slashes)
- Scope has billable resources in the date range
- Date range configuration is correct (MonthToDate vs. custom)
- No conflicting Azure Policy deny assignments
- Managed identity (if used) is active and not deleted
- Export execution history shows recent attempts
- Storage account hasn't been moved to different subscription/region
- No recent changes to storage account networking
- Files searched in correct container and path
- Data latency accounted for (24-48 hours normal)
When to Contact Azure Support
Contact Azure Support if:
- Export consistently fails despite correct permissions
- Data discrepancies between Cost Management UI and exported files
- Platform errors (HTTP 500, service unavailable)
- Suspected Azure service issue (check Azure Status first)
- Managed identity issues that can't be resolved
- Data loss or corruption in export files
- Unexpected charges appearing in exports
Before contacting support, gather:
- Export configuration (JSON output from
az costmanagement export show) - Export execution history (last 30 days)
- Storage account diagnostic logs (if enabled)
- Screenshots of errors
- Correlation IDs from failed runs
Next Steps
After resolving export issues:
- Set up monitoring to detect future failures early
- Document your configuration for disaster recovery
- Automate validation to ensure exports complete successfully
- Review export scope to ensure capturing all necessary costs
- Optimize file format (consider Parquet for large exports)
- Implement data pipeline to process exports automatically
Related Resources
Frequently Asked Questions
Find answers to common questions
Need Professional Help?
Our team of experts can help you implement and configure these solutions for your organization.