Help us improve
Share bugs, ideas, or general feedback.
From shopify-pack
Diagnoses common Shopify API errors (401, 403, 422, 429, GraphQL) with real responses, causes, and fixes like curl tests and scope reconfiguration.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin shopify-packHow this skill is triggered — by the user, by Claude, or both
Slash command
/shopify-pack:shopify-common-errorsThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Quick-reference guide for the most common Shopify API errors with real error messages, causes, and fixes.
Identifies Shopify API anti-patterns like ignoring userErrors, outdated versions, REST over GraphQL, missing GDPR webhooks, and timeouts. Reviews code with real examples.
Use Shopify GraphQL Admin API for server CRUD on products/orders and Storefront API for client queries on products/cart, with versioning, rate limits, bulk ops, pagination.
Writes or explains Shopify Admin GraphQL queries and mutations for apps and integrations extending the admin. Use for understanding, designing, or generating operations before execution or config validation.
Share bugs, ideas, or general feedback.
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.
Actual Shopify Response:
{
"errors": "[API] Invalid API key or access token (unrecognized login or wrong password)"
}
Causes:
X-Shopify-Access-Token headerFix:
# Verify token format:
# Admin API token: shpat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (32 hex chars)
# Storefront API token: different format, starts with shpat_ too
curl -s -o /dev/null -w "%{http_code}" \
-H "X-Shopify-Access-Token: $SHOPIFY_ACCESS_TOKEN" \
"https://your-store.myshopify.com/admin/api/2024-10/shop.json"
# Should return 200
Actual Shopify Response:
{
"errors": "This action requires merchant approval for read_orders scope."
}
Cause: Your app's access token lacks the required scope.
Fix: Add the needed scope to your app config and re-trigger OAuth:
# shopify.app.toml
[access_scopes]
scopes = "read_products,write_products,read_orders,write_orders"
Actual Shopify Response:
{
"errors": "Not Found"
}
Causes:
Fix:
# Verify the API version exists
curl -s "https://your-store.myshopify.com/admin/api/2024-10/shop.json" \
-H "X-Shopify-Access-Token: $TOKEN"
# Check available API versions
curl -s "https://your-store.myshopify.com/admin/api/versions.json" \
-H "X-Shopify-Access-Token: $TOKEN"
Actual Shopify Responses:
{
"errors": {
"title": ["can't be blank"],
"handle": ["has already been taken"]
}
}
{
"errors": {
"base": ["Product cannot be saved: Title is too long (maximum is 255 characters)"]
}
}
Common 422 triggers:
Fix: Check the errors object or userErrors array for specific field-level messages.
REST API Response:
HTTP/1.1 429 Too Many Requests
Retry-After: 2.0
GraphQL Response (in body, returns 200):
{
"errors": [
{
"message": "Throttled",
"extensions": {
"code": "THROTTLED",
"documentation": "https://shopify.dev/api/usage/rate-limits"
}
}
],
"extensions": {
"cost": {
"requestedQueryCost": 752,
"actualQueryCost": null,
"throttleStatus": {
"maximumAvailable": 2000,
"currentlyAvailable": 0,
"restoreRate": 100
}
}
}
}
Fix: See shopify-rate-limits skill for complete backoff implementation.
Critical: Shopify returns HTTP 200 even when mutations fail.
{
"data": {
"productCreate": {
"product": null,
"userErrors": [
{
"field": ["title"],
"message": "Title can't be blank",
"code": "BLANK"
}
]
}
}
}
Always check userErrors after every mutation:
const response = await client.request(mutation, { variables });
const result = response.data.productCreate;
if (result.userErrors.length > 0) {
// These are validation errors, NOT HTTP errors
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, but you must handle them.
{
"errors": "Internal Server Error"
}
Fix: Retry with exponential backoff. Include the X-Request-Id header value when reporting to Shopify support.
// The X-Request-Id header is in every Shopify response
const requestId = error.response?.headers?.["x-request-id"];
console.error(`Shopify 500 error. Request ID: ${requestId}`);
| 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 |
#!/bin/bash
STORE="your-store.myshopify.com"
TOKEN="$SHOPIFY_ACCESS_TOKEN"
VERSION="2024-10"
echo "=== Shopify Diagnostic ==="
# 1. Test auth
echo -n "Auth: "
curl -s -o /dev/null -w "%{http_code}" \
-H "X-Shopify-Access-Token: $TOKEN" \
"https://$STORE/admin/api/$VERSION/shop.json"
echo ""
# 2. Check scopes
echo "Scopes:"
curl -s -H "X-Shopify-Access-Token: $TOKEN" \
"https://$STORE/admin/oauth/access_scopes.json" | python3 -m json.tool
# 3. Check API versions
echo "API Versions:"
curl -s -H "X-Shopify-Access-Token: $TOKEN" \
"https://$STORE/admin/api/versions.json" | python3 -c "
import json, sys
versions = json.load(sys.stdin)['supported_versions']
for v in versions[:5]:
print(f' {v[\"handle\"]} {\"(latest)\" if v.get(\"latest\") else \"\"}')"
# 4. Shopify status
echo "Shopify Status: https://www.shopifystatus.com"
For comprehensive debugging, see shopify-debug-bundle.