applyShippingAddressChange silently ignores address1 in Brazilian checkouts — same call applies provinceCode and drops address1 (2025-07 and 2026-07)

Environment

  • Checkout UI extension, target purchase.checkout.delivery-address.render-after
  • Reproduced on api_version = "2025-07" (React) and api_version = "2026-07" (Preact + Polaris web components, @shopify/ui-extensions 2026.7.1, preact 10.29.8, @preact/signals 2.11.0)
  • Shopify Plus development store, Brazilian delivery address form, native address autocomplete enabled

What we’re building

A postal code (CEP) validator: when the buyer enters a CEP, we fetch the official street from our postal code service and keep the delivery address consistent — correcting street, city and province when they diverge.

City and province work perfectly. The street never applies.

The core evidence

A single call, one payload, two fields:

await shopify.applyShippingAddressChange({
  type: "updateShippingAddress",
  address: {
    provinceCode: "SC",
    address1: "Rodovia Haroldo Soares Glavan",
  },
});

// → {type: "success", errors: null}
//
// provinceCode: applied
// address1:     unchanged ("Estrada Haroldo Soares Glavan 31231")


Same call, same instant, same payload object. provinceCode is written, address1 is silently discarded, and the result reports success with errors: null.

Minimal repro

  1. BR delivery address form, complete and valid address (first/last name, CEP, street, number, city, province).
  2. From an extension on purchase.checkout.delivery-address.render-after, apply a change that includes address1 and any other address field.
  3. The other field is applied; address1 is not. Result is success.

What we ruled out

  • Value format. Tried "Street", "Street, 123", "Street⁠123" and "Street, ⁠123" (with U+2060 WORD JOINER). We compared code points on both sides and sent byte-identical formatting to what the checkout itself produces. Ignored in every case.
  • Payload shape. {address1}, {address1, zip}, {address1, address2, zip, city, provinceCode}. Ignored.
  • Missing subfield. We hypothesized the checkout might reject an address1 it can’t split into street and number. Tried both a street-only value (leaving the number empty) and a well-formed street + ", " + U+2060 + number. Both ignored.
  • Address validity. Tried with all required fields filled and with the number missing. Ignored either way. Note that a full payload including names on an incomplete address does return a real error ({"message":"Enter a last name","field":"lastName"}), so the mutation validates and can report errors — it just never reports anything about address1.
  • Concurrency. Serialized to a single in-flight write.
  • Rate limiting. Ruled out by the two-field call above, which applied provinceCode in a fresh session.
  • API version. Same behavior on 2025-07 and 2026-07.

Our current theory

In the BR checkout, address1 looks like a derived value, not a field. Inspecting the delivery form inputs:

streetName   = "Rodovia Haroldo Soares Glavan"      ← real input
streetNumber = "767"                                ← real input
district / line2 / city / zone / postalCode         ← real inputs
address1     = "Rodovia Haroldo Soares Glavan, ⁠767" ← hidden, composed from the two

The checkout appears to recompose address1 from streetName + streetNumber and discard external writes. city and provinceCode work because they map 1:1 to real inputs. Meanwhile streetName / streetNumber are not exposed by the Checkout UI Extensions API, and they don’t exist in the LocalizedFieldKey union (which only has TAX_CREDENTIAL_* and SHIPPING_CREDENTIAL_*).

Questions

  1. Is writing address1 supported in locales that use the split street/number address form (BR and similar)? If not, is this documented?
  2. If it isn’t supported, could applyShippingAddressChange return a field-level error for the ignored field instead of success? A silent no-op is extremely expensive to diagnose.
  3. Is there any supported way to set the street programmatically in these locales — an API for streetName / streetNumber — or is purchase.address-autocomplete.suggest the only intended path?

Three side notes that may save others time

  • The separator inside address1 is invisible. BR uses ", " plus a WORD JOINER (U+2060) between street and number, and JSON.stringify does not escape U+2060 — so it’s invisible in any log inspected that way. We reached two wrong conclusions before printing code points explicitly.
  • Rate limiting is indistinguishable from this bug. Per the docs, an extension that makes too many changes “can’t make further changes during the buyer’s session”. While rate limited, calls still resolve with type: "success" and do nothing. The TooManyChangesError only surfaced as an uncaught exception inside our async handler. Reflecting that state in the result — or in a readable API property — would help a lot.
  • Migrating to Preact needs an explicit JSX pragma. The docs’ migration example shows import '@shopify/ui-extensions/preact'; import {render} from 'preact'; with no pragma. Without /** @jsxImportSource preact */ in the file, our build produced vnodes from a different JSX runtime and mounting failed with TypeError: Cannot add property __, object is not extensible. Worth adding to the migration guide.

Thanks for the bug report, Gabriel. I was able to reproduce the issue and we’ve created an internal issue to track a fix.