Error codes.
Every error of subkit and shopkit has a code and links here – as docsUrl of the thrown error and in the docs field of HTTP responses. Find the code, read the cause, apply the fix.
Coding agents: the docs MCP server at https://agentkit.ch/mcp explains a code with explain_error.
subkit
Subscriptions, invoices and the self-service API.
- CUSTOMER_NOT_FOUNDHTTP 404
Cause: No billing customer with this
externalId– it is created on the first subscription or withupsertCustomer().Fix: Call
upsertCustomer({ externalId, email, name })first, or check the id.- PLAN_NOT_FOUNDHTTP 404
Cause: The
planIdis not among theplanspassed tosubkit().Fix: Use an id from the configured plans (the MCP tool
list_planslists them).- PLAN_NOT_PURCHASABLEHTTP 400
Cause: The plan has no price for this interval, or it is hidden (no longer sold).
Fix: Offer only the intervals in
plan.prices. A hidden plan stays with its subscribers but cannot be bought.- SUBSCRIPTION_EXISTSHTTP 400
Cause: The customer already has a running subscription.
Fix: Change the plan with
changePlan()instead ofsubscribe().- NO_SUBSCRIPTIONHTTP 400
Cause: The action needs a running subscription, and the customer has none (never subscribed, or it ended).
Fix: Start one with
subscribe().getOverview()shows the current state.- INVALID_STATEHTTP 400
Cause: Not possible in the current state: the checkout of the subscription is unfinished, or an open invoice has to be settled before a plan change.
Fix: Finish or cancel the checkout, or pay the open invoice, then try again.
- PAYMENT_METHOD_REQUIREDHTTP 400
Cause: An upgrade is charged right away and needs a saved card or TWINT – there is none.
Fix: Let the customer add one (
POST …/payment-method) or switch to invoice.- PAYMENT_FAILEDHTTP 400
Cause: The charge of an upgrade was declined (card declined, not enough funds, TWINT refused). The plan stays as it was.
Fix: Ask the customer to update the payment method, then try again.
- PROVIDER_UNAVAILABLEHTTP 503
Cause: The payment provider could not be reached or answered with an error (this is not a declined card).
Fix: Try again later. Check the provider’s status and the API key (zahls.ch: instance and key).
- INVOICE_NOT_FOUNDHTTP 404
Cause: No invoice with this id for this customer – or, when paying, no open one.
Fix: Check the id and that the invoice belongs to the signed-in customer.
- OVERDUE_INVOICEHTTP 402
Cause: An invoice of the customer is overdue or written off; nothing new is sold until it is paid.
Fix: Pay it first (
POST …/invoices/:id/payor by QR-bill), then try again.- COLLECTION_METHOD_UNAVAILABLEHTTP 400
Cause: This payment option (card / TWINT or invoice) is not enabled in
collectionMethodsof the handler.Fix: Add it to
collectionMethods, or offer only the enabled options.- BUSYHTTP 409
Cause: Another request is changing the same subscription, order, cart or stock at this moment (e.g. a renewal or a webhook).
Fix: Try again in a moment – nothing is lost.
- RATE_LIMITEDHTTP 429
Cause: Your
rateLimitcallback refused the request, or too many webhooks arrived for one payment.Fix: Wait the seconds in
Retry-After. If real customers hit the limit, raise it.- WEBHOOK_INVALIDHTTP 400
Cause: A webhook could not be verified: unknown transaction, amount or currency differ, or the body is not JSON.
Fix: Point the provider’s webhook (format JSON) to
…/webhookand use the same instance and API key as the kit. Forged requests end here on purpose.- UNAUTHORIZEDHTTP 401
Cause: The
authorize(oridentify) callback of the handler did not accept the request – no session, or no access.Fix: Send the session cookie or token with the request and check the callback.
- UNSUPPORTED_MEDIA_TYPEHTTP 415
Cause: A POST without
Content-Type: application/json. The handlers require it as CSRF protection.Fix: Send JSON with exactly this content type – the React clients of the kits already do.
- INVALID_JSONHTTP 400
Cause: The request body is not valid JSON.
Fix: Send a JSON object as the body.
- INVALID_INPUTHTTP 400
Cause: A field is missing, has the wrong type or is out of range (e.g. an unknown interval, a negative amount, a link that is not http(s)).
Fix: Check the field the message names against the README of the kit.
- NOT_FOUNDHTTP 404
Cause: No route for this method and path below the
basePathof the handler.Fix: Check that
basePathmatches where the route is mounted, and the HTTP method.- INTERNAL_ERRORHTTP 500
Cause: An unexpected error (database, bug). The details are not sent to the client.
Fix: Look at
onErrorand the server log. A bug in a kit: report it with the stack trace.
shopkit
Catalog, cart, checkout, orders and the back office API.
- PRODUCT_NOT_FOUNDHTTP 404
Cause: No product with this id or slug.
Fix: Check id or slug. Archived products are only in the back office.
- VARIANT_NOT_FOUNDHTTP 404
Cause: No variant with this id.
Fix: Use an id from
product.variants.- NOT_FOR_SALEHTTP 400
Cause: The product or variant is a draft or archived.
Fix: Activate it in the back office, or remove it from the cart.
- OUT_OF_STOCKHTTP 409
Cause: Fewer items in stock than asked for (stock is reserved at checkout).
Fix: Lower the quantity – the message says how many are left.
- INVALID_QUANTITYHTTP 400
Cause: A quantity below 1 or above the maximum per line, or too many items in the cart.
Fix: Use a whole number within the limit the message names.
- CART_NOT_FOUNDHTTP 404
Cause: No cart with this token (a wrong token, or an old cart that was abandoned).
Fix: Create a new cart – the React provider does this by itself.
- CART_EMPTYHTTP 400
Cause: Checkout of a cart without items.
Fix: Add items first.
- CART_CLOSEDHTTP 409
Cause: The cart was already turned into an order.
Fix: Show the order, or start a new cart.
- DISCOUNT_INVALIDHTTP 400
Cause: Unknown, expired, inactive or used-up discount code.
Fix: Check the code in the back office (
list_discounts).- DISCOUNT_NOT_APPLICABLEHTTP 400
Cause: The code is valid, but this cart does not qualify (minimum order value, products).
Fix: Meet the conditions, or remove the code.
- GIFT_CARD_INVALIDHTTP 400 · 404
Cause: Unknown, disabled or expired gift card, or its balance is too low.
Fix: Check the code (dashes and case do not matter) and the balance.
- EMAIL_REQUIREDHTTP 400
Cause: Checkout without an email address.
Fix: Set
emailin the cart details (updateCartDetails()).- ADDRESS_REQUIREDHTTP 400
Cause: Physical items need a shipping address.
Fix: Set
shippingAddressin the cart details.- SHIPPING_RATE_REQUIREDHTTP 400
Cause: Physical items, but no shipping method chosen.
Fix: Set
shippingRateIdto one of the offered rates.- SHIPPING_RATE_UNAVAILABLEHTTP 400
Cause: The chosen shipping method does not exist or does not fit this cart.
Fix: Pick one of the
shippingOptionsof the cart.- FULFILLMENT_DATE_REQUIREDHTTP 400
Cause: The chosen shipping rate has a
schedule, but the cart has no pickup or delivery day yet – or no time window although there are some.Fix: Set a day from
shippingOptions[].schedule.dates(and a window fromtimeWindows) withupdateCartDetails({ fulfillmentDate, fulfillmentWindow }).- FULFILLMENT_DATE_UNAVAILABLEHTTP 400
Cause: The day or time window is not (or no longer) offered: before the lead time, after the cutoff, on a closed day or beyond
maxDays.Fix: Choose a day from the current
schedule.datesof the shipping rate – the list changes over time and with the products in the cart.- PAYMENT_METHOD_UNAVAILABLEHTTP 400
Cause: The payment method (online or invoice) is not offered for this shop or order, or no provider is configured.
Fix: Configure the provider and the methods in
createShop(), or choose another method.- PAYMENT_METHOD_NOT_FOUNDHTTP 404
Cause: The customer has no (such) saved payment method: none saved yet, removed, refused by the provider and deactivated, or it belongs to another customer.
Fix: Order without
useSavedPaymentMethod(payment link) and let the customer save one withsavePaymentMethod: true.- AMOUNT_CHANGEDHTTP 409
Cause: The amount due differs from the one the customer confirmed (
expectedAmount), e.g. because a price, discount or shipping changed. Nothing was charged.Fix: Quote the order again (
quoteOrder/quote_order), show the customer the new amount and order again with the confirmed amount.- ORDER_NOT_FOUNDHTTP 404
Cause: No order with this id, or the token of the order link does not match.
Fix: Check the id and the
tokenof the order link.- INVALID_STATEHTTP 409
Cause: Not possible in the state of the order: paid already, cannot be paid, not paid yet (refund), canceled.
Fix: Read
status,paymentStatusandfulfillmentStatusof the order first.- REFUND_TOO_HIGHHTTP 400
Cause: The refund is more than what is left to refund, or the gift cards of the order were used already.
Fix: Refund at most the amount in the message.
- DUPLICATEHTTP 409
Cause: A product slug, SKU or discount code with this value exists already.
Fix: Choose another one, or change the existing record.
- PROVIDER_UNAVAILABLEHTTP 503
Cause: The payment provider could not be reached or answered with an error (this is not a declined card).
Fix: Try again later. Check the provider’s status and the API key (zahls.ch: instance and key).
- BUSYHTTP 409
Cause: Another request is changing the same subscription, order, cart or stock at this moment (e.g. a renewal or a webhook).
Fix: Try again in a moment – nothing is lost.
- RATE_LIMITEDHTTP 429
Cause: Your
rateLimitcallback refused the request, or too many webhooks arrived for one payment.Fix: Wait the seconds in
Retry-After. If real customers hit the limit, raise it.- WEBHOOK_INVALIDHTTP 400
Cause: A webhook could not be verified: unknown transaction, amount or currency differ, or the body is not JSON.
Fix: Point the provider’s webhook (format JSON) to
…/webhookand use the same instance and API key as the kit. Forged requests end here on purpose.- NO_PAYMENT_SLIPHTTP 400
Cause: A bank import, but the back office handler has no payment slip to compute the references.
Fix: Pass
receipts.paymentSlip(e.g.swissQrBill()) tocreateShopAdminHandler().- INVALID_CAMTHTTP 400
Cause: The bank file is not a camt.053 or camt.054 XML document.
Fix: Export camt.054 (or camt.053) as XML from e-banking and send it as
{ "camt": "<?xml …" }.- HSSOFT_REJECTEDHTTP 502
Cause: HS-Soft (WaWiAssist) refused the request: invalid API key, a channel the key may not write, a locked order date, an order that is already invoiced or an unknown article.
error.details.typenames the reason.Fix: Fix the cause (check the API key with HS-Soft, correct the date or article) and send the order again with
syncOrder(id, { force: true }). Retrying unchanged will not help.- HSSOFT_UNAVAILABLEHTTP 503
Cause: HS-Soft could not be reached or failed temporarily (503, timeout, gateway error).
Fix:
syncOrders()tries again by itself afterretryMinutes. If the order isuncertain, first check in WaWiAssist whether it arrived – only then send it again.- HSSOFT_UNMAPPEDHTTP 422
Cause: An order line or the shipping costs have no HS-Soft article – the product does not come from the import.
Fix: Import the product from HS-Soft, set
orders.articleIdororders.shippingArticleId, or leave the order out withorders.filter.- SWISSPOST_REJECTEDHTTP 502
Cause: Swiss Post refused the request: client or scopes of the Digital Commerce API, the franking licence, a combination of services the item cannot have, an address Swiss Post cannot deliver to – or an item abroad (labels are for Switzerland and Liechtenstein).
error.details.errorslists the Swiss Post codes (E2001…).Fix: Fix the cause (check client and scopes with Swiss Post, the licence, the services of the shipping rate or the address) and create the label again. Retrying unchanged will not help.
- SWISSPOST_UNAVAILABLEHTTP 503
Cause: Swiss Post could not be reached or failed temporarily (timeout, 5xx, E9999).
Fix: Create the label again later. Address suggestions and the address check at checkout do not fail because of it – the order goes on without them.
- UNAUTHORIZEDHTTP 401
Cause: The
authorize(oridentify) callback of the handler did not accept the request – no session, or no access.Fix: Send the session cookie or token with the request and check the callback.
- UNSUPPORTED_MEDIA_TYPEHTTP 415
Cause: A POST without
Content-Type: application/json. The handlers require it as CSRF protection.Fix: Send JSON with exactly this content type – the React clients of the kits already do.
- INVALID_JSONHTTP 400
Cause: The request body is not valid JSON.
Fix: Send a JSON object as the body.
- INVALID_INPUTHTTP 400
Cause: A field is missing, has the wrong type or is out of range (e.g. an unknown interval, a negative amount, a link that is not http(s)).
Fix: Check the field the message names against the README of the kit.
- NOT_FOUNDHTTP 404
Cause: No route for this method and path below the
basePathof the handler.Fix: Check that
basePathmatches where the route is mounted, and the HTTP method.- METHOD_NOT_ALLOWEDHTTP 405
Cause: The back office API accepts only GET and POST.
Fix: Use POST for changes.
- TOO_LARGEHTTP 413
Cause: The request body is too large (100 kB; bank files 20 MB).
Fix: Send less – split a large bank file, for example.
- INTERNAL_ERRORHTTP 500
Cause: An unexpected error (database, bug). The details are not sent to the client.
Fix: Look at
onErrorand the server log. A bug in a kit: report it with the stack trace.