Consistent reads are not supported on global secondary indexes

TL;DR — グローバル** セカンダリインデックスを対象とする Query または ScanConsistentRead: true を設定しました。GSI はベーステーブルから非同期にレプリケートされ、結果整合性のある読み取りしか提供しません。このフラグは好みではなく、致命的なエラーです。フラグを外すか、read-after-write の整合性が本当に必要なら、ベーステーブルを読む(またはキーを LSI に設計する)ようにしてください。**

意味

ValidationException: Consistent reads are not supported on global secondary indexes

GSI は物理的に独自のパーティションとキャパシティを持つ独自のインデックス構造です。DynamoDB はベーステーブルの書き込みを非同期にそこへ伝播します。今書き込んだアイテムがまだインデックスに届いていない可能性があるため、DynamoDB はそれに対する強い整合性のある読み取りを実現できません。したがって、ConsistentRead: true と GSI の IndexName を組み合わせると、そのまま拒否されます。AWS のドキュメントは明示的です: ConsistentRead を true にして GSI を照会すると ValidationException を受け取ります。

ローカル セカンダリインデックスは異なります。LSI はパーティションをベーステーブルと共有するため、そこでは ConsistentRead: true がサポートされます。

発生する理由

  • フラグがグローバルに設定されていた — 共有のクエリヘルパーやクライアントラッパーがすべての読み取りに ConsistentRead: true をデフォルトで設定し、ある呼び出し経路が GSI を指す IndexName を追加している。
  • LSI が GSI になった — ローカルインデックス用(フラグが合法)に書かれたコードが、グローバルインデックスに向けられた。
  • コピペしたベーステーブルクエリ — テーブルで正当に強い整合性を使っていたクエリが、IndexName を追加して再利用された。

修正方法

  1. GSI 読み取りから ConsistentRead を削除します(または false に設定 — デフォルト):

    await client.send(
      new QueryCommand({
        TableName: 'Orders',
        IndexName: 'status-index',
        KeyConditionExpression: '#s = :open',
        // ConsistentRead: true  ← delete this line for a GSI
        ExpressionAttributeNames: {'#s': 'status'},
        ExpressionAttributeValues: {':open': {S: 'OPEN'}}
      })
    );
  2. read-after-write が必要ですか? ConsistentRead: trueベーステーブル を照会します。探しているキーがテーブル自身のパーティションキーであれば、いつでも可能です。

  3. 同じパーティションキーで別のソート? それを LSI(テーブル作成時に作成)としてモデリングします。LSI は整合性のある読み取りをサポートします。

  4. またはアプリケーションで遅延を吸収します — GSI の伝播は通常高速です。UI フローでは、すでに手元にある書き込み直後のデータを返す方が、インデックスを再読み取りするより優れています。

DynoTable デスクトップアプリ は各テーブルのインデックスを表示し、直接照会できます。そしてどのインデックスがグローバルでどれがローカルかを把握しているため、この種のエラーはそもそも発生しません。

関連するエラー

References

最終検証日 2026-07-13、上記にリンクした公式 AWS ドキュメントに照らして確認しました。

Console なしで DynamoDB を扱う

DynoTable は DynamoDB 向けの高速なデスクトップクライアントです — テーブルを閲覧し、SQL スタイルのクエリを実行し、アイテムをローカルで編集できます。