Quick-reference guide for the most common Shopify API errors with real error messages, causes, and fixes.
Check whether the error is an HTTP status code error or a GraphQL userErrors response.
Response: "[API] Invalid API key or access token (unrecognized login or wrong password)"
Causes: Access token expired (merchant uninstalled/reinstalled), wrong header, or using Storefront token for Admin API.
Fix: Verify token format (shpat_ + 32 hex chars) and test with a simple shop.json GET request.
Response: "This action requires merchant approval for read_orders scope."
Fix: Add the needed scope to shopify.app.toml under [access_scopes] and re-trigger OAuth.
Causes: Wrong API version in URL, resource was deleted, or store domain is incorrect.
Fix: Verify the API version exists by checking /admin/api/versions.json.
Common triggers: Missing required fields, duplicate handle/slug, invalid metafield type, price format issues (must be string like "29.99"), invalid country/province codes.
Fix: Check the errors object or userErrors array for specific field-level messages.
REST returns 429 with Retry-After header. GraphQL returns 200 with THROTTLED error code in the body and zero currentlyAvailable points.
Fix: See shopify-rate-limits skill for complete backoff implementation.
Critical: Shopify returns HTTP 200 even when mutations fail. Always check userErrors after every mutation:
const result = response.data.productCreate;
if (result.userErrors.length > 0) {
for (const err of result.userErrors) {
console.error(`Field ${err.field?.join(".")}: ${err.message} (${err.code})`);
}
throw new Error("Shopify validation failed");
}
Shopify internal errors -- not your fault. Retry with exponential backoff and capture the X-Request-Id header for support tickets.
| Status | Name | Retryable | Action |
|---|---|---|---|
| 401 | Unauthorized | No | Re-authenticate, verify token |
| 403 | Forbidden | No | Add missing scope, re-OAuth |
| 404 | Not Found | No | Check URL, API version, resource ID |
| 422 | Unprocessable | No | Fix validation errors in request body |
| 429 | Throttled | Yes | Backoff using Retry-After header |
| 500 | Server Error | Yes | Retry with backoff, report X-Request-Id |
| 503 | Unavailable | Yes | Shopify is overloaded, retry later |
Run auth, scope, and API version checks in one pass.
See Diagnostic Script for the complete shell script.