Cost Query Error Handling
Detailed error handling reference for the Cost Management Query API.
HTTP Status Codes
| Status | Error | Cause | Remediation |
|---|---|---|---|
| 400 | BadRequest | Invalid request body, unsupported dimension, date range exceeds limits, malformed filter expression. | Validate request body against request-body-schema.md. Check dimension compatibility in dimensions-by-scope.md. |
| 401 | Unauthorized | Missing or expired authentication token. | Re-authenticate with az login or refresh the bearer token. |
| 403 | Forbidden | Insufficient permissions on the target scope. User lacks Cost Management Reader or equivalent role. | Assign Cost Management Reader or Cost Management Contributor role on the scope. |
| 404 | NotFound | Scope does not exist, subscription not found, or resource group does not exist. | Verify the scope URL. Confirm the subscription ID and resource group name are correct. |
| 429 | TooManyRequests | Rate limit exceeded. QPU, entity, or tenant throttling triggered. | Check all x-ms-ratelimit-microsoft.costmanagement-*-retry-after headers (qpu, entity, tenant). Wait for the longest value before retrying. |
| 503 | ServiceUnavailable | Cost Management service is temporarily unavailable. | Check Azure Status for service health. |
Common Error Scenarios
| Error Message / Scenario | Cause | Remediation |
|---|---|---|
| "Agreement type X does not support Y scope" | Scope type is incompatible with the account's agreement type. | Use a compatible scope. EA accounts cannot use Invoice Section scope; MOSP accounts cannot use Department scope. |
| "Dimension Z is not valid for scope" | The requested dimension is not available for the current scope and agreement type combination. | Check dimensions-by-scope.md for valid dimensions. |
| "SubscriptionName filter without SubscriptionId" | EA + Management Group scope: filtering by SubscriptionName without also filtering by SubscriptionId. | Add a SubscriptionId filter alongside the SubscriptionName filter. See guardrails.md. |
| Date range exceeds granularity limit | Daily range > 31 days or Monthly/None range > 12 months. | System auto-truncates from date. To avoid silent truncation, ensure range is within limits. |
| Date range exceeds absolute limit (37 months) | from to to spans more than 37 months. | Reduce the date range to 37 months or less. Split into multiple queries if needed. |
| "Request body is null or invalid" | Missing or malformed JSON in the request body. | Validate JSON syntax. Ensure type, timeframe, and dataset fields are present. |
| Invalid filter structure | and/or has fewer than 2 child expressions, or not has more than 1. | Ensure and/or contain 2+ children. Use not with exactly 1 child. For single conditions, use the filter directly without a logical wrapper. |
| "The query usage is not supported for the scope" | The query type (e.g., AmortizedCost) is not supported at the given scope. | Try a different scope or query type. Not all scopes support all report types. |
BillingSubscriptionNotFound | The subscription ID in the scope URL is invalid or not associated with the billing account. | Verify the subscription ID exists and is active. Check that it belongs to the expected billing account. |
Retry Strategy
| Status | Retry? | Strategy |
|---|---|---|
| 429 | ✅ Yes | Check the response for all x-ms-ratelimit-microsoft.costmanagement-*-retry-after headers (qpu-retry-after, entity-retry-after, tenant-retry-after). Take the longest value and do NOT retry until that duration has fully elapsed. Maximum 3 retries. |
| 400 | ❌ No | Fix the request. Review error message for specific field or validation issue. |
| 401 | ❌ No | Re-authenticate. Token has expired or is missing. |
| 403 | ❌ No | Fix permissions. Request appropriate RBAC role assignment on the scope. |
| 404 | ❌ No | Fix the scope URL. Verify resource exists. |
| 503 | ❌ No | Do not retry. Check Azure Status for service health. |
| 5xx (other) | ❌ No | Do not retry. Investigate the error and check service health. |
⚠️ Warning: Do not retry any errors except 429. All other errors indicate issues that must be fixed before re-attempting the request.
Error Response Structure
All error responses follow a consistent JSON structure:
{
"error": {
"code": "<error-code>",
"message": "<human-readable-error-message>",
"details": [
{
"code": "<detail-code>",
"message": "<detail-message>"
}
]
}
}| Field | Description |
|---|---|
error.code | Machine-readable error code (e.g., BadRequest, BillingSubscriptionNotFound). |
error.message | Human-readable description of the error. |
error.details | Optional array of additional detail objects with more specific error information. |