---
title: Handle errors and budgets
description: >-
  Handle failed ShopifyQL queries, stay within complexity-based rate limits, and
  account for in-progress reporting periods when you query from an app.
source_url:
  html: >-
    https://shopify.dev/docs/apps/build/shopifyql/graphql-admin-api/errors-limits-and-performance
  md: >-
    https://shopify.dev/docs/apps/build/shopifyql/graphql-admin-api/errors-limits-and-performance.md
---

# Handle errors and budgets

When you run ShopifyQL from an app, you need to handle queries that fail, requests that hit the rate limit, and reporting periods that are still filling in. This page covers how to catch each error, read your remaining budget before you hit the limit, and keep the numbers you display accurate.

***

## Handle failed queries

When a query fails, the error shows up in one of two fields, `parseErrors` or `errors`, depending on what went wrong. Check both fields before you read the results.

### Parse errors

A syntactically invalid query still returns a `200 OK` response. `tableData` is null, and the error appears in the [`shopifyqlQuery`](https://shopify.dev/docs/api/admin-graphql/latest/queries/shopifyqlQuery) response's `parseErrors` array. Check `parseErrors` before you read `tableData`.

## JSON response

```json
{
  "data": {
    "shopifyqlQuery": {
      "tableData": null,
      "parseErrors": [
        "Column Not Found: Column 'total_revenue' not found"
      ]
    }
  }
}
```

### Graph​QL errors

Authentication failures or a missing [`read_reports`](https://shopify.dev/docs/api/usage/access-scopes#authenticated-access-scopes) access scope return as standard `errors`. The `data` payload is null. Check `errors` before you read `data`, and handle them like any other GraphQL Admin API error.

## JSON response

```json
{
  "data": null,
  "errors": [
    {
      "message": "Access denied for shopifyqlQuery field. Required access: read_reports access scope.",
      "extensions": {
        "code": "ACCESS_DENIED",
        "documentation": "https://shopify.dev/api/usage/access-scopes"
      }
    }
  ]
}
```

For the full response shape and status codes, refer to [error handling in the GraphQL Admin API](https://shopify.dev/docs/apps/build/graphql/migrate/learn-how#understanding-error-handling).

***

## Stay within the complexity budget

ShopifyQL [rate limits](https://shopify.dev/docs/api/usage/rate-limits) are based on query complexity. Heavier queries cost more against your budget. A query's complexity grows with:

* The number of keywords and clauses you use.
* The number of metrics in `SHOW`.
* The number of dimensions in `GROUP BY`.

To lower a query's cost, request only the metrics and dimensions you'll display, and drop clauses you don't need.

### Read your remaining budget

The `shopifyqlQuery` response returns a `shopifyqlCost` object in the GraphQL `extensions`. Read it to check a query's cost and your remaining budget before you hit a `429`.

## JSON response

```json
{
  "extensions": {
    "shopifyqlCost": {
      "requestedQueryCost": 1,
      "maximumAvailable": 1000,
      "currentlyAvailable": 999,
      "windowResetAt": "2026-07-16T07:06:00+00:00"
    }
  }
}
```

The object has four fields:

* `requestedQueryCost`: The complexity cost of the query you ran.
* `maximumAvailable`: The most budget available in a window.
* `currentlyAvailable`: The budget left in the current window.
* `windowResetAt`: When the window resets and the budget refills.

A `shopifyqlQuery` request draws down two budgets, both returned in `extensions`. `shopifyqlCost`, shown above, is the ShopifyQL-specific budget. The standard GraphQL Admin API [`cost`](https://shopify.dev/docs/api/usage/rate-limits) budget applies too, and every other GraphQL Admin API call your app makes shares it. Either budget can return a `429`. The ShopifyQL budget is the smaller of the two, and it's usually the first to run out.

When a query exceeds the ShopifyQL budget, the API returns a `429`. Wait until the `windowResetAt` timestamp before you retry.

***

## Account for data freshness

The current reporting period is still filling in. A query that includes today returns a partial day, and today's total climbs as new orders land. Querying the same range an hour later can return a higher number.

What you do about it depends on what you're showing:

* **For stable totals**, like a monthly report or a number you reconcile against the store's own reports, exclude the in-progress period. Running `SINCE startOfDay(-30d) UNTIL endOfDay(-1d)` snaps the range to whole days with [date functions](https://shopify.dev/docs/api/shopifyql/latest/syntax/since-until-during#date-functions) and drops today's partial data. The total won't move after you read it.
* **For a live view**, like sales so far today, expect the latest point to climb as orders land. Label it with the fetch time to signal that the number is still in progress.

### Cache results

Completed periods don't change. A cached result stays correct until the period you're querying advances. Caching cuts latency for users and lowers the query complexity you spend against the rate limit.

Match how long you cache to the query's smallest time bucket:

* Totals over months or all time can cache for hours.
* A daily or hourly view can cache for a few minutes.

Key each cache entry by the store and the exact query string. Results differ by both, and a shared key returns the wrong store's data or stale rows for a query you changed.

***

## Next steps

You've now handled what changes when a ShopifyQL query runs in a live app. To see it wired into a full build, work through the sales dashboard. To write leaner queries that cost less, learn the full query language.

[Build a sales dashboard with the GraphQL Admin API\
\
](https://shopify.dev/docs/apps/build/shopifyql/graphql-admin-api/build-a-sales-dashboard)

[Send a query through the `shopifyqlQuery` field and read the structured results, ready to render in your app.](https://shopify.dev/docs/apps/build/shopifyql/graphql-admin-api/build-a-sales-dashboard)

[ShopifyQL reference\
\
](https://shopify.dev/docs/api/shopifyql)

[Review the full syntax, datasets, metrics, and dimensions.](https://shopify.dev/docs/api/shopifyql)

***
