コンテンツにスキップ

Schema Mismatch

  • push / pull リクエストが HTTP 409 を返し、body が { "error": "schema mismatch", "expected": "..." } になる
  • client.onError{ kind: "schema-mismatch", phase, expected } で発火する
  • Devtools パネルに「schema mismatch」バッジが表示される

Worker 側の SyncHandlerOptions.schemaVersion が、ブラウザクライアント側の PlasmaClientOptions.schemaVersion と一致していません。サーバーは未知の schema version 下での mutation の受け入れを拒否します。

  1. 共有ファイルの SCHEMA_VERSION を上げたが、サーバーをデプロイしていない。 クライアントのビルドは v2 だが、デプロイ済みの Worker は依然として v1 を 実行している。
  2. サーバーを先にデプロイした。 Worker は v2 だが、ユーザーの キャッシュされたクライアントビルドは依然として v1 のまま。
  3. ドリフトした 2 つの schema.ts ファイルがある。 Worker 側のコピーと クライアント側のコピーが、うっかり異なる文字列定数を持っている。

対処 — サーバーが古すぎる場合

Section titled “対処 — サーバーが古すぎる場合”

追いつくために Worker をデプロイします。

Terminal window
pnpm wrangler deploy

その後、新しいバージョンが push を受け取っていることをログストリームで確認します。

Terminal window
pnpm wrangler tail

対処 — クライアントが古すぎる場合

Section titled “対処 — クライアントが古すぎる場合”

ユーザーが古いバンドルをキャッシュしている場合、リロードしてもらう必要があります。 最もクリーンな UX は次のとおりです。

createPlasmaClient({
...,
onSchemaMismatch: async ({ phase }) => {
if (confirm("This app has been updated. Reload to continue?")) {
window.location.reload()
return "stay"
}
return "stay"
},
})

"stay" を返すとローカルの IDB はそのまま残ります。ユーザーはリロードするまで 先に進めません。あるいは "reset" を返してローカルの IDB をワイプすることもできます (下記のトレードオフを参照)。

戻り値 効果
"stay" ローカルの IDB はそのまま。mismatch が解消されるまで sync ループは失敗し続けます。ユーザーはローカルの mutation を続けられます (outbox に溜まります)。
"reset" ローカルの IDB をワイプ: base ストア、user ストア、outbox、cookie、clientID がすべてローテートされます。次の pull でゼロからハイドレートします。
  • SCHEMA_VERSION を意図的に上げる。 どの変更が bump を必要とし、 どの変更が必要としないかは Migrations を参照してください。
  • クライアントより先にサーバーをデプロイする。 サーバーは古いクライアントの schema version を暗黙に受け入れます (追加必須カラムが欠けていない限り)。 新しいクライアントが古いサーバーに当たるのが失敗モードです。
  • バンドルにバージョンを付ける。 JS バンドルの Cache-Control は、 バージョン bump 時の迅速なリロードを促すべきです。

onSchemaMismatch の UX をテストするために、ローカルで mismatch を強制します。

dev.ts
const plasma = createPlasmaClient({
...,
schemaVersion: "wrong-version", // ≠ what the Worker returns
})