The table lists each error code, typical HTTP status, and how to handle it in client code.
AUTH_REQUIRED
HTTP 401 Default message Sign in to save items.
When it occurs
The storefront customer is not signed in; app proxy requests lack a valid `logged_in_customer_id` on the signed URL; or the direct-API bearer token is missing, invalid, or expired.
Client handling
Show a sign-in prompt and retry after login. For app proxy, only call SaveLayer when Liquid/session indicates a logged-in customer. For headless/customer-account, re-exchange for a fresh bearer token.
CUSTOMER_REQUIRED
HTTP 401 Default message Customer must be logged in to access this resource.
When it occurs
Not emitted by SaveLayer app proxy or direct API ingress today. Reserved in the contract for a future distinct case (e.g. shop expects a different login mode). Proxy integrations: expect AUTH_REQUIRED (401) when the customer is not logged in.
Client handling
If you ever receive this code, handle like AUTH_REQUIRED. New integrations should key on AUTH_REQUIRED for missing customer context on the Online Store channel.
INVALID_PROXY_SIGNATURE
HTTP 401 Default message The app proxy signature is invalid.
When it occurs
Shopify’s app-proxy HMAC verification failed (query params or shared secret mismatch).
Client handling
Never construct proxy URLs manually without Shopify’s signed parameters. Use theme/app extension links or Liquid-generated app proxy URLs. Merchants: reinstall or confirm app proxy URL and secret in Partner settings.
INVALID_HEADLESS_SIGNATURE
HTTP 401 Default message The headless authorization signature is invalid.
When it occurs
The headless channel request failed cryptographic verification (wrong secret, stale timestamp, or malformed signature).
Client handling
Regenerate the request using the documented signing algorithm and current credentials. Rotate secrets if compromised. Do not expose signing keys in browser bundles.
INVALID_LEGACY_STOREFRONT_TOKEN
HTTP 401 Default message The legacy Storefront customer access token is invalid or could not resolve a customer.
When it occurs
The legacy Storefront customer access token or the shop's Storefront access token is invalid, expired, or could not resolve a customer via the Storefront API.
Client handling
Verify both the customer access token and the shop's public Storefront access token are current. Prefer migrating to the modern Customer Account API path when possible.
INVALID_EXTENSION_SESSION
HTTP 401 Default message The customer account session is invalid.
When it occurs
The customer account extension session token was missing, expired, or failed validation.
Client handling
Refresh the extension session or ask the shopper to re-open the account UI. Avoid caching tokens beyond their lifetime.
SHOP_NOT_INSTALLED
HTTP 403 Default message The shop is not fully installed.
When it occurs
The shop domain is known but SaveLayer is not installed or the install record is incomplete.
Client handling
Merchant must complete app installation from the Shopify admin. Storefronts should hide or disable save UI when the app is unavailable.
FORBIDDEN
HTTP 403 Default message You do not have access to this resource.
When it occurs
Authenticated context exists but the operation is not allowed for this customer or resource (authorization failure).
Client handling
Do not retry blindly. Confirm the customer owns the list/item or that the correct list scope is used. Show a generic “access denied” message.
LIST_NOT_FOUND
HTTP 404 Default message The requested list could not be found.
When it occurs
The referenced save list does not exist or is not visible to this customer.
Client handling
Refresh list state from the server. If the user bookmarked an old list ID, redirect to the default list or an empty state.
ITEM_NOT_FOUND
HTTP 404 Default message The requested item could not be found.
When it occurs
Remove, toggle, or update targeted a save item that does not exist (or was already removed).
Client handling
Treat as idempotent success for “remove” UX when appropriate, or refresh the list UI. Avoid assuming the item still exists after errors.
VALIDATION_ERROR
HTTP 400 Default message The request payload is invalid.
When it occurs
JSON body failed schema validation, required fields are missing, or values are out of allowed shape (including invalid JSON).
Client handling
Log the response body in development only. Fix payloads to match the published request schemas (entity type, GIDs, limits). Surface a generic “something went wrong” for shoppers.
UNSUPPORTED_ENTITY_TYPE
HTTP 400 Default message The requested entity type is not supported.
When it occurs
The requested entity type is not in SaveLayer’s supported set for this API version.
Client handling
Use only supported entity types from the integration docs. Gate UI so unsupported product shapes never call save APIs.
INDEX_UPDATE_DEFERRED
HTTP 400 Default message The index update was deferred.
When it occurs
An index or denormalized customer metafield update was intentionally deferred (operational soft-failure).
Client handling
Optional refresh after a short delay. Core save/list data in metaobjects remains authoritative; index lag should not block primary UX.
DUPLICATE_SAVE
HTTP 409 Default message The item is already saved.
When it occurs
The customer attempted to save an entity that is already present in the target list.
Client handling
Update UI to “saved” state without alarming the user. Safe to treat as success for idempotent “save” buttons.
BATCH_CONFLICT
HTTP 409 Default message Batch contains conflicting operations on the same item.
When it occurs
A batch request contains multiple operations targeting the same item (same context, entity type, and entity GID).
Client handling
Deduplicate operations client-side before sending. Each item should appear at most once per batch request.
BATCH_NOT_ALLOWED
HTTP 403 Default message Batch operations are not available on your current plan.
When it occurs
The merchant's plan does not include batch operations (e.g. Free plan).
Client handling
Fall back to individual save/remove calls, or prompt the merchant to upgrade to a plan that supports batch operations.
BATCH_TOO_LARGE
HTTP 422 Default message Batch size exceeds your plan's limit.
When it occurs
The number of operations in the batch exceeds the plan's maxBatchSize limit.
Client handling
Split the batch into smaller chunks within the plan's batch size limit. Check the plan's maxBatchSize via the usage endpoint.
RATE_LIMITED
HTTP 429 Default message Too many requests. Please try again shortly.
When it occurs
Request volume exceeded configured rate limits for the shop or route.
Client handling
Honor Retry-After if present; otherwise exponential backoff. Debounce rapid clicks on save buttons and batch operations where possible.
PLAN_LIMIT_REACHED
HTTP 402 Default message The plan limit has been reached.
When it occurs
The merchant’s plan or usage caps block further writes (billing / entitlement).
Client handling
Show merchant-facing messaging in admin; storefront can show a soft capacity message. Merchants must upgrade or reduce usage.
CHANNEL_NOT_ALLOWED
HTTP 403 Default message This channel is not available on your current plan.
When it occurs
The request arrived on a channel (headless, customer-account) that is not included in the merchant’s current plan.
Client handling
Show a contextual upgrade prompt explaining which plan unlocks the requested channel. Do not retry on the same channel without a plan change.
MAX_LISTS_REACHED
HTTP 402 Default message You've reached the maximum number of save lists on your plan.
When it occurs
The customer or merchant has reached the maximum number of save lists allowed by the current plan.
Client handling
Prompt the merchant to upgrade for more lists, or guide the customer to use an existing list instead of creating a new one.
CANNOT_DELETE_DEFAULT_LIST
HTTP 409 Default message The default list cannot be deleted. Set another list as the default first.
When it occurs
A delete-list request targeted the customer’s default save list while it was still marked as default.
Client handling
Call set-default with another list ID first, then retry delete. Refresh list UI so the user picks a new default before removing the old default list.
SHOPIFY_UPSTREAM_ERROR
HTTP 502 Default message Shopify returned an upstream error.
When it occurs
Shopify Admin or Storefront API returned an error, timeout, or unexpected response while SaveLayer processed the request.
Client handling
Retry with backoff for transient cases. If persistent, merchant should check Shopify status and app scopes. Do not assume data was written—re-fetch state.
INTERNAL_ERROR
HTTP 500 Default message An internal error occurred.
When it occurs
An unexpected exception occurred server-side after validation (bug, infrastructure, or unhandled edge case).
Client handling
When `retryable` is true, retry with backoff a few times. Otherwise show a generic error and support contact. Never rely on error message text for branching logic—use `code`.