Cart API の書き込みは 「POS が確認しないと reject」に変わる
原題: Cart mutations reject unconfirmed writes in POS UI extensions 2026-10
- POS UI extensions
- Cart API
- 破壊的変更
- 仕様変更
- API versioning
- Error handling
- Discounts
- Selling Plans
- Migration
- 2026-10
図解 : POS UI extensions 2026-10 : 未確認のカート書き込みは reject されるように POS UI extensions / 2026-10 破壊的変更 Cart API の書き込みは 「POS が確認しないと reject」に変わる これまではカートが実際に変わっていなくても mutation は成功(resolve)扱いでした。2026-10 からは POS が書き込みを確認できない場合に promise が reject されるため、すべての呼び出し箇所でエラー処理が必要になります。 このページの構成 そもそも何が変わるのか(30秒で理解) 仕組み図解 : 2026-07 以前と 2026-10 の違い 対象になる Cart API mutation reject 時の 2 つのメッセージ 影響を受けるアプリ/受けないアプリ 移行手順とコード例 技術者が押さえるべき5つのポイント 業務に活かせる3つのユースケース 提案で使える1行サマリ 1 そもそも何が変わるのか POS はすべてのカート書き込みについて結果を返しており、カートが変わったと確認できるのは success の結果だけ です。 API バージョン 2026-10 からは、POS が書き込みを確認できない限り Cart API の mutation は reject されます。これまで見えなかった「書き込みの取りこぼし」が、呼び出し元のエラーとして表に出てきます。 2026-07 以前 : 結果に関係なく resolve POS が書き込みを反映したかどうかに関係なく mutation は resolve します。そのため、反映された書き込みと取りこぼされた書き込みをアプリが区別できず、カートは変わっていないのに手数料や割引を「適用済み」と表示してしまうことがあります。 2026-10 : 確認できなければ reject POS が書き込みを確認したときだけ resolve します。確認できなければ reject され、アプリはリトライする・スタッフにメッセージを出す・自分の state をロールバックする、といった対応をその場で取れます。 2 仕組み図解 : 2026-07 以前と 2026-10 の違い なぜ重要か : 現状、カート書き込みの取りこぼしは 何も言わずに起きる ため気づけません。reject にすることで、この「気づかれないデータ欠損」が呼び出し元のエラーとして見えるようになります。 3 対象になる Cart API mutation 2026-10 で「未確認なら reject」になるもの(15 個) カート・明細 bulkCartUpdate removeLineItem カート割引 applyCartDiscount addCartCodeDiscount removeAllDiscounts 顧客 setCustomer removeCustomer 明細プロパティ addLineItemProperties bulkAddLineItemProperties removeLineItemProperties 明細割引 setLineItemDiscount bulkSetLineItemDiscounts removeLineItemDiscount 販売プラン addLineItemSellingPlan removeLineItemSellingPlan ※ カテゴリ分けはこのページで読みやすくするためのもので、元記事にはありません。 2026-10 で新しく追加されたもの NEW updateLineItemQuantity 2026-10 で新しく追加された mutation で、最初のリリースから「未確認なら reject」の仕様です。古い挙動のバージョンはありません。 4 reject 時の 2 つのメッセージ 拒否された(カートは変わっていない) POS refused the cart update. The cart was not changed. POS が書き込みを受け付けなかったケースで、カートは変わっていません。レジ担当が支払いに進んだ後など、POS がカートの変更をもう受け付けていないときに起きます。カートを編集できる状態に戻れば、 リトライで成功する可能性があります 。 確認できなかった(結果は不明) POS could not confirm the cart update. 結果が分からず、 一部だけ書き込まれている可能性 もあります。 リトライする前にカートを読み直す 必要があります。 この 2 つのメッセージは「未確認の書き込み」専用です。cart mutation は、割引の値が不正、顧客が見つからないといった 別の理由でも reject されます 。メッセージで判定するのは、この 2 ケースを区別したいときだけにしてください。 ケース カートの状態 推奨される対処 refused 変化なし カートを編集できる状態に戻ってからリトライ could not confirm 不明(一部書き込みの可能性) カートを読み直してからリトライ その他の reject 記載なし 不正な割引値・顧客が見つからない等、原因ごとに対処 5 影響を受けるアプリ/受けないアプリ 影響あり 2026-10 以降を宣言した extension api_version = "2026-10" 以降の POS UI extension から、上記の mutation を 1 つでも呼んでいるアプリ。 影響なし 2026-07 以前のまま 今の挙動がそのまま続きます。2026-07 は API バージョニングのサポート期間が終わるまで使えます。 挙動が変わる すでに try/catch を書いている 未確認の書き込みでも成功したものとして処理を続けるのではなく、既存の catch / .catch() ハンドラが実行されるようになります。 適用単位は ストアではなく extension ごと です。各 extension が宣言している API バージョンで決まります。 6 移行手順とコード例 注意 : これまで resolve していた呼び出しが reject するようになります。 reject を catch しないと、ハンドラの残りの処理は実行されません。書き込み後に描画する UI や、ローディング状態を解除するといった後片付けも含めて止まります。 Before await shopify.cart.applyCartDiscount('FixedAmount', 'Winter discount', '5.00'); setDiscountApplied(true); After try { await shopify.cart.applyCartDiscount('FixedAmount', 'Winter discount', '5.00'); setDiscountApplied(true); } catch (error) { setDiscountApplied(false); showToast('Could not update the cart. Try again before payment.'); } 1 呼び出し箇所を洗い出す extension の中で、対象の cart mutation を呼んでいるすべての場所を確認します。 2 それぞれに reject 処理を入れる try/catch か .catch() を入れ、state を戻す・メッセージを出す処理を書きます。 3 api_version = "2026-10" に上げる エラー処理が入ってからバージョンを上げます。 すぐに移行できない場合は、2026-07 以前のままにしておきます。 影響は受けないので、エラー処理を入れ終わってからバージョンを上げれば大丈夫です。エラー処理を入れずに上げると、最初の未確認書き込みでハンドラが止まり、スピナーが出たままになったり確認ステップが飛ばされたりします。 7 技術者が押さえるべき5つのポイント 1. catch しない await は後続処理ごと止まる reject が catch されないと、書き込み後の UI 描画もローディング解除も実行されません。「スピナーが消えない」「確認ステップが飛ばされる」が典型的な症状です。後片付けはエラー時にも通る場所に置く必要があります。 2. 「拒否」と「不明」でリトライ方針が違う refused はカートが変わっていないので、編集できる状態に戻ればそのままリトライできます。could not confirm は一部だけ書き込まれた可能性があるので、 まずカートを読み直してから リトライします。何も考えずにリトライすると二重適用の恐れがあります。 3. メッセージで分岐するのは必要なときだけ 不正な割引値や顧客が見つからないなど、2 つのメッセージ以外の理由でも reject されます。基本はすべての reject を catch で受け、2 ケースを区別したいときだけメッセージで判定します。 4. 切り替えは extension ごと 影響範囲はストアではなく、各 extension の api_version で決まります。複数の extension を持つアプリでは、一つずつエラー処理を入れてから上げる段階的な移行ができます。 5. 新しい updateLineItemQuantity は最初から reject 前提 2026-10 で追加された updateLineItemQuantity は、最初のリリースから reject する仕様です。この mutation に乗り換える場合、「resolve したらカートが変わった」と前提にして、最初から catch を書く設計にします。 8 業務に活かせる3つのユースケース USE CASE 1 割引・手数料の「適用済み表示なのに未反映」をなくす 課題 POS extension で割引や手数料を入れたとき、カートは変わっていないのに「適用済み」と表示されることがある(2026-07 以前の挙動)。 打ち手 呼び出し箇所すべてに try/catch を入れ、catch でフラグを戻してトーストを出す(記事の After 例)。そのうえで api_version = "2026-10" に上げる。 効果 気づかれずに起きていた書き込みの取りこぼしが、スタッフに見えるエラーになる。支払い前にやり直せる。 技術メモ catch の中で UI の state(例: setDiscountApplied(false) )を戻す。ローディング解除も忘れずに。 USE CASE 2 reject の種類に応じたリトライ処理をアプリ共通で用意する 課題 reject の中身が「拒否(カートは変わっていない)」か「不明(一部書き込みの可能性)」かで、正しいリトライ方法が違う。 打ち手 2 つのメッセージで判定し、拒否はカートを編集できる状態に戻ってからリトライ、不明はカートを読み直してからリトライする。それ以外の reject は理由ごとに処理する。 効果 何も考えずにリトライして起きる二重適用を避けつつ、リトライで成功するケースは自動で拾える。 技術メモ メッセージで分岐するのは 2 ケースを区別したいときだけにする。既定の動作は「すべての reject を catch」。 USE CASE 3 複数の POS extension を一つずつ安全に 2026-10 へ移行する 課題 カートを操作する extension がいくつもあり、一度に全部直すのは難しい。 打ち手 エラー処理を入れ終わった extension から api_version を 2026-10 に上げる。まだのものは 2026-07 のままにしておく。 効果 適用単位が extension ごとなので、本番の挙動を壊さずに段階的に移行できる。 技術メモ 2026-07 は API バージョニングのサポート期間が終わるまで動く。期限は記事に記載なし。API versioning のドキュメントで確認すること。 9 提案で使える1行サマリ 「POS UI extensions 2026-10 では、POS が確認できないカート書き込みが reject されるようになります。 気づかれずに起きていた書き込みの取りこぼしがエラーとして見えるので、呼び出し箇所すべてに catch を入れてからバージョンを上げましょう。 間に合わない extension は 2026-07 のままで大丈夫です。」 source : shopify.dev / changelog / cart-mutations-reject-unconfirmed-writes-in-pos-ui-extensions-2026-10 公開日 2026-10-07(Developer Changelog)