Cart/checkout validation runs too often

Hey, I have a cart/checkout validation that exits early if buyerJourney.step is either missing or not equal to CHECKOUT_COMPLETION. This validation is meant to run when the buyer is completing checkout—ideally, when they click the “Pay now” button. However, it appears to trigger earlier in the buyer journey, such as when they interact with the shipping address or shipping methods. This causes an error banner to appear at an unexpected stage, which can be confusing for buyers. Is this behavior intentional, or could it be a bug?

This is not a bug. The cart and checkout validation function can target error messages in the following specific checkout UI fields:

  • cart: $.cart
  • email: $.cart.buyerIdentity.email
  • phone: $.cart.buyerIdentity.phone
  • address1: $.cart.deliveryGroups[0].deliveryAddress.address1
  • address2: $.cart.deliveryGroups[0].deliveryAddress.address2
  • city: $.cart.deliveryGroups[0].deliveryAddress.city
  • company: $.cart.deliveryGroups[0].deliveryAddress.company
  • countryCode: $.cart.deliveryGroups[0].deliveryAddress.countryCode
  • firstName: $.cart.deliveryGroups[0].deliveryAddress.firstName
  • lastName: $.cart.deliveryGroups[0].deliveryAddress.lastName
  • phone: $.cart.deliveryGroups[0].deliveryAddress.phone
  • provinceCode: $.cart.deliveryGroups[0].deliveryAddress.provinceCode
  • zip: $.cart.deliveryGroups[0].deliveryAddress.zip

Since Shopify allows targeted error messages for these fields, it is expected behavior for the validation to trigger during different stages of the buyer journey, such as when interacting with shipping or address information.

To block checkout progress, use useBuyerJourneyIntercept. For more details, refer to the documentation: Shopify API - useBuyerJourneyIntercept.

Blocking checkout progress behavior doesn’t apply to express checkout options, such as Shop Pay, Google Pay, and Apple Pay.

`

Yes, but my problem is with CHECKOUT_COMPLETION running too often. Not with the function overall. For those fields the expected step is CHECKOUT_INTERACTION.

I’ve previously implemented cart and checkout validation using a similar approach and haven’t faced any problems. In my code, I return the error at the beginning of the code, if the buyer journey status isn’t equal to CHECKOUT_COMPLETION, ensuring that validation only runs at the correct stage, typically when the buyer clicks the “Pay now” button.

Here’s an example in Rust:

if buyer_journey != "CHECKOUT_COMPLETION" {
    return Ok(output::FunctionRunResult { errors });
}

This way, the validation doesn’t trigger at earlier steps, like interacting with the shipping address or shipping methods, which might prevent the unexpected error banners you mentioned.

Same here.

Query Input :

query RunInput {
	buyerJourney {
		step
	}
	cart {
		lines {
			quantity
		}
	}
}

run.js

export function run(input) {
	const { step } = input.buyerJourney;
	const errors =
		step === 'CHECKOUT_COMPLETION'
			? [
				{
					localizedMessage: 'Not possible to order more than one of each',
					target: '$.cart',
				},
			  ]
			: [];
	return { errors };
}

I’ve deployed a cart and checkout validation function and tested it thoroughly across all scenarios. We didn’t encounter any validation errors when interacting with the shipping address or shipping methods. The validation only triggered during the CHECKOUT_COMPLETION step, as expected.

Thanks @AMaL ! Apparently I confused errors from Functions validation with the ones from useBuyerJournery hook, as they look exactly the same. The hook was the problem!