# Shopify cart and checkout validation in 2026

Cart and Checkout Validation Functions: server-side rules, field targets, Checkout Rules activation, and Storefront API userErrors.

- Date: 2026-10-17
- Category: Shopify

## Table of contents

- Why Shopify cart and checkout validation matters in 2026
- How Cart and Checkout Validation Functions run
- Production checklist for Shopify cart and checkout validation
- What breaks when validation Functions go live
- How I measure Shopify cart and checkout validation
- Related work on this site
- FAQ
  - What is Shopify cart and checkout validation?
  - How do I activate a cart and checkout validation function?
  - Can Shopify cart and checkout validation block Storefront API carts?
  - What changed for billing address and PO validation in 2026?

Shopify cart and checkout validation is how I enforce business rules on the server instead of hoping a theme script or a checkout UI extension catches every edge case. I am Alan Vo, a Gold Coast web developer with 18 years in production. When a Plus store needs to block oversize carts, cap first-time buyers, or require a PO number on B2B checkout, Cart and Checkout Validation Functions belong in the same migration bucket as [Shopify checkout extensibility deadlines in 2026](https://alanvo.com/blog/shopify-checkout-extensibility/).

This note is for merchants and developers who already accept that checkout.liquid and Shopify Scripts are sunset paths. It covers the `cart.validations.generate.run` target, how Shopify surfaces errors to buyers, what changed in 2026 for billing address and PO fields, and how I test before a peak season.

## Why Shopify cart and checkout validation matters in 2026

Shopify cart and checkout validation matters because client-side checks are easy to bypass and expensive Scripts are going away. A JavaScript guard on the cart page does not run inside Shop Pay, does not protect the Storefront API cart mutations, and disappears when a buyer uses an accelerated wallet. Validation Functions run in Shopify's checkout pipeline after pricing and discount Functions, which is the order Shopify documents in its [Function APIs overview](https://shopify.dev/docs/api/functions/latest).

The platform treats a validation error as a hard stop. When your function returns a `validationAdd` operation with errors, checkout cannot advance until the cart state changes or the rule no longer fires. That is stronger than a UI extension banner that a theme update can hide. It is also different from a discount Function: you are not changing line prices, you are declaring that the order is not allowed to proceed.

Merchants activate validations under **Settings > Checkout > Checkout rules** (wording may vary slightly by admin version). Each rule points at one deployed Function. Multiple rules can stack, but I prefer one well-tested function per concern so rollback is obvious.

2026 added server-side hooks for billing address fields and purchase order numbers on the validation input graph, with matching checkout field targets for error messages. Shopify's [April 2026 changelog entry](https://shopify.dev/changelog/posts/cart-and-checkout-validation-adds-billing-address-and-po-number-error-targets) describes `billingAddress` and `poNumber` on the cart input and targets such as `$.cart.billingAddress.countryCode` and `$.cart.poNumber`. That closes a gap where teams used fragile UI extensions to block prohibited billing countries or B2B orders without a PO.

If you still rely on a Ruby Script to reject carts, the Scripts sunset timeline in my checkout extensibility note applies. Validation Functions are the supported replacement surface for "should this cart be allowed to check out?"

![Shopify cart and checkout validation on a laptop showing a Shopify storefront layout](../../images/blog/shopify-cart-checkout-validation-1.jpg)

## How Cart and Checkout Validation Functions run

Cart and Checkout Validation Functions use the target `cart.validations.generate.run`. Your app ships a Function extension. Shopify invokes it with a GraphQL input query you define (for example cart subtotal, buyer order count, line attributes, delivery address, and as of 2026-04 billing address and PO number where applicable). The Function returns a `CartValidationsGenerateRunResult` with an ordered list of operations, typically `validationAdd` blocks that contain one or more errors.

Each error has a `message` string shown to the buyer and a `target` string that tells Shopify where to attach the error in checkout. The [Cart and Checkout Validation Function API reference](https://shopify.dev/docs/api/functions/latest/cart-and-checkout-validation) documents global cart targeting with `$.cart` and field-level targets that mirror checkout field paths. Field-level targeting is how you put a postal code error on the postal code field instead of flashing a generic banner at the top of the step.

Functions execute in WebAssembly with strict time and memory limits. Shopify's overview stresses performance because validations sit on the purchase path. I keep input queries minimal: fetch only fields the rule reads, avoid unbounded line loops when a cart attribute or subtotal check is enough, and never assume you can call the Admin API from inside the Function runtime unless you use the documented `fetch` pattern for external validation providers (and account for latency).

The execution order relative to other Functions is fixed. Cart line transforms and discount Functions run first. Validations run last among the standard checkout Function family. That means your validation sees discounted totals, not pre-discount fiction. It also means you cannot validate your way out of a bad discount Function; fix the discount layer first.

Checkout UI extensions can still complement validations. I use UI extensions for helpful copy and validations for rules that must hold on every surface. Duplicating the same rule in JavaScript and in a Function is a maintenance trap. Pick one source of truth for enforcement.

## Production checklist for Shopify cart and checkout validation

The production checklist starts with a written rule spec, then scaffold, then activation on a duplicate store before touching production checkout rules.

1. Write the rule in merchant language first: "First-time customers cannot checkout over $1,000 AUD" or "Billing country must not be on our restricted list." Include what should happen on Shop Pay and on headless carts.
2. Scaffold a Function app with Shopify CLI using the cart and checkout validation template. Shopify's tutorial [Create checkout validation](https://shopify.dev/docs/apps/build/checkout/cart-checkout-validation/create-checkout-validation) walks through GraphQL input, Rust or JavaScript handler, and deploy.
3. Shape the input query to match the rule. The tutorial example reads `buyerIdentity.customer.numberOfOrders` and `cart.cost.subtotalAmount.amount`. Extend only when you need line attributes, delivery groups, or the 2026 billing and PO fields.
4. Return `validationAdd` with a clear buyer-facing message. Avoid internal codes in the string merchants see.
5. Set `target` deliberately. Use `$.cart` for order-level blocks. Use field paths when the buyer can fix a specific input.
6. Deploy the app to a development store and enable the validation under checkout rules. Confirm the rule name matches what support will search for in admin.
7. Test happy path checkout end to end: standard shipping, discount codes, and at least one wallet if the merchant uses Shop Pay.
8. Test failure path: attempt checkout with a cart that should fail. Verify the buyer cannot reach shipping or payment until the cart changes.
9. Test Storefront API behavior. Shopify documents that `cartLinesAdd` and related mutations surface function validation messages in `userErrors`. Headless storefronts must render those errors instead of swallowing them.
10. Test B2B PO rules on a store with B2B features if applicable. Confirm `poNumber` is present in input when you expect it and that errors land on the PO field target.
11. Test billing country restrictions with the new address subfield targets. A message on `countryCode` is easier to act on than a generic cart error.
12. Document rollback: which checkout rule to disable and which app version to pin if a deploy misbehaves during a sale.
13. Align analytics. A blocked checkout is not a conversion. If you map checkout steps in GTM via a [Shopify custom pixel for Google Tag Manager](https://alanvo.com/blog/shopify-gtm-custom-pixel/), decide whether validation failures get an event or stay out of the funnel noise.
14. After Scripts sunset, remove duplicate Ruby checks so buyers do not see two conflicting messages.

![Clothing rails in a shop used as a live catalogue for Shopify cart and checkout validation](../../images/blog/shopify-cart-checkout-validation-2.jpg)

## What breaks when validation Functions go live

The most common break is an over-broad input query that pushes the Function over resource limits on large carts. Symptoms are intermittent checkout failures or rules that never seem to run. Shrink the query and simplify logic before you ask Shopify to raise limits (which is not guaranteed).

![Theme code on a monitor during Shopify cart and checkout validation work](../../images/blog/shopify-cart-checkout-validation-3.jpg)

The second break is wrong targets. A typo in `target` still returns an error, but Shopify may show it as a global checkout message. Buyers do not know which field to fix. Copy targets from the API reference, do not guess path strings from checkout DOM ids.

The third break is stale buyer identity assumptions. `numberOfOrders` and customer fields depend on login state and checkout identity. Guest checkout with an email that matches a returning customer behaves differently than a logged-in account. Test guests, logged-in customers, and B2B company locations if the store uses them.

The fourth break is fighting discount Functions. If a validation reads pre-discount subtotal in your head but the input exposes post-discount amounts, thresholds feel "wrong" to merchandisers. Read the actual input schema fields and name the rule after post-discount totals in the spec.

The fifth break is headless carts that ignore `userErrors`. Hydrogen and custom apps must bubble validation failures to the UI. Otherwise support hears "Shopify blocked me" while the storefront shows a generic failure.

The sixth break is double enforcement. A UI extension that disables the Pay button plus a Function that blocks checkout can produce duplicate messaging. Pick server-side enforcement and use UI for education only.

## How I measure Shopify cart and checkout validation

Measurement starts with structured logs on the app side, not only Shopify admin. I log function version, rule id, and a hash of cart line count when a validation returns errors in staging. In production I avoid logging PII; I log rule name and outcome counts.

In checkout analytics, compare step drop-off before and after enabling a rule. A spike on the information step after turning on billing country validation usually means the message or target is unclear, not that buyers hate the policy.

Support ticket tags help. If agents start pasting the exact validation message daily, the copy is either working (buyers quote it) or the rule is too aggressive for the catalog mix.

For B2B PO requirements, measure orders that complete after PO entry versus abandoned checkouts where PO was empty. If abandonment rises with no lift in compliant orders, the rule timing may be wrong (require PO before payment, not after).

Storefront API teams should track mutation `userErrors` rates in their own telemetry. Silent failures there are conversion leaks.

## Related work on this site

Validation Functions sit beside checkout extensibility work I have shipped on Plus stores. [Their Nibs](https://alanvo.com/work/their-nibs/) is a Shopify build where checkout trust, tags, and conversion hygiene had to stay aligned through platform migrations. [Offporter](https://alanvo.com/work/offporter/) is another Shopify storefront where checkout-side behavior and merchandising rules cannot drift from what the theme promises. [Tamannaah Fine Jewellery](https://alanvo.com/work/tamannaah-fine-jewellery/) is the kind of high-SKU catalogue where cart limits and regional rules show up in support if enforcement is only client-side.

![Phone showing a product page in Shopify cart and checkout validation testing](../../images/blog/shopify-cart-checkout-validation-4.jpg)

If you are still mapping the extensibility surface area, read [Shopify checkout extensibility deadlines in 2026](https://alanvo.com/blog/shopify-checkout-extensibility/) before you schedule Function work behind a hard launch date.

## FAQ

### What is Shopify cart and checkout validation?

Shopify cart and checkout validation is a Checkout Extensibility feature that runs Cart and Checkout Validation Functions on Shopify's servers during checkout. The function evaluates cart and buyer data, then returns validation errors that block progress until the buyer fixes the cart or the rule no longer applies. It replaces many legacy Script-based guards for order eligibility.

### How do I activate a cart and checkout validation function?

You deploy a Function app extension, install the app on the store, then enable the validation under checkout rules in admin (**Settings > Checkout**). Shopify's [create checkout validation tutorial](https://shopify.dev/docs/apps/build/checkout/cart-checkout-validation/create-checkout-validation) covers scaffolding, deploy, and verifying that checkout stops when the rule fires. Test on a development store before enabling on production.

### Can Shopify cart and checkout validation block Storefront API carts?

Yes. When a validation function returns errors, Storefront API cart mutations can include those messages in `userErrors`, and checkout cannot complete while the validation fails. Custom storefronts must display `userErrors` to buyers. Relying only on Online Store checkout without testing API paths leaves a hole in enforcement.

### What changed for billing address and PO validation in 2026?

As of API version 2026-04, Cart and Checkout Validation Function input includes `billingAddress` and `poNumber` on the cart object, with checkout field targets for billing address subfields and `$.cart.poNumber`. That lets functions enforce billing country restrictions and B2B PO requirements without client-only UI extensions, as described in Shopify's [changelog post](https://shopify.dev/changelog/posts/cart-and-checkout-validation-adds-billing-address-and-po-number-error-targets).


![Card payment at a counter after a Shopify cart and checkout validation release](../../images/blog/shopify-cart-checkout-validation-5.jpg)


HTML version: https://alanvo.com/blog/shopify-cart-checkout-validation/
