Value provided in ExpressionAttributeNames unused in expressions
TL;DR — どの式からも参照されない名前のプレースホルダー(例: #status)を ExpressionAttributeNames に宣言しています。DynamoDB は、宣言したすべてのエイリアスが KeyConditionExpression、FilterExpression、UpdateExpression、ConditionExpression、ProjectionExpression のいずれかで使われることを要求します。使われていないエイリアスを削除するか、参照するはずだった式を修正してください。
意味
ValidationException: 1 validation error detected: Value provided in ExpressionAttributeNames unused in
expressions: keys: {#status}
# what the engine actually returns, reproduced against DynamoDB Local:
ValidationException: 1 validation error detected: Value provided in ExpressionAttributeNames unused in expressions: keys: {#status}ExpressionAttributeNames は、属性名のエイリアスのための置換マップです(予約語や特殊文字を含む名前に必要)。DynamoDB は厳格な双方向の契約を強制します。式で使うすべてのエイリアスは宣言されていなければならず、かつ 宣言したすべてのエイリアスは使われていなければなりません。参照されずに残ったエントリがあると、この HTTP 400 の ValidationException が発生します。これはクライアント側の問題であり、マップと式が一致するまでリトライしても無駄です。
発生する理由
- 式を編集した後に残った古いエイリアス — 式から
#status = :sを削除したのに、名前マップから#statusを消し忘れた。 - 過剰に宣言する生成マップ — マッピング層が、最終的な式が触れない属性まで含めてすべてのエイリアスを出力した。
- エイリアスが名前マップではなく値マップの話だった —
:status(値)のつもりで#status(名前)を宣言した。 - タイプミスによる不一致 — 式は
#statを使い、マップは#statusを宣言しているので、#statusは技術的に未使用。
修正方法
- メッセージが名指ししている未使用のエイリアスを
ExpressionAttributeNamesから削除します。 - マップと式を歩調を合わせて保ちます — 式が実際に参照するときだけ
#nameを宣言します。 - 名前と値の取り違えを確認します —
#エイリアスはExpressionAttributeNamesに、:プレースホルダーはExpressionAttributeValuesに属します。 - リクエストを生成し直します — 名前・値・式のテキストを手で組み立てるのではなく、一緒に組み立てるようにします。
DynoTable で調べる
DynoTable は更新エディタとフィルターエディタで予約語の属性名にエイリアスを付けます — 出力に現れる #placeholder はすべて式から参照されています。⌘K でテーブルを開き、アイテムを編集して、生成された ExpressionAttributeNames のマップをコピーしてください。
失敗する SDK リクエストは予約語チェッカーで突き合わせましょう — # プレフィックスが必要な名前について、エイリアスのマップを出力してくれます。プロファイルの切り替えは ⌘P です。AWS に接続するとインストールを参照してください。
出典
- Expression attribute names (aliases) in DynamoDB (2026-07-13 時点で検証)
- Reserved words in DynamoDB (2026-07-13 時点で検証)
再現方法
どの式からも参照されない ExpressionAttributeNames のエントリです。
await client.send(
new UpdateItemCommand({
TableName: 'orders',
Key: {pk: {S: 'ORDER#1'}, sk: {S: 'META'}},
UpdateExpression: 'SET stat = :v', // note: 'stat', not '#unused'
ExpressionAttributeNames: {'#unused': 'status'},
ExpressionAttributeValues: {':v': {S: 'shipped'}}
})
);実際の出力:
ValidationException: 1 validation error detected: Value provided in ExpressionAttributeNames unused in expressions: keys: {#unused}
HTTP 400メッセージが問題のキーを名指ししてくれるので、これはほかに何も読まずに対処できる数少ない DynamoDB のバリデーションエラーの1つです。たいていは、編集で式からプレースホルダーを取り除いたのに、その宣言を残したままにしたときに現れます。
関連するエラー
- Value provided in ExpressionAttributeValues unused in expressions —
:valueプレースホルダーに対する同じルール。 - The provided expression refers to an attribute that does not exist in the item — 式がアイテムに存在しない属性を読んでいる。
- Attribute name is a reserved keyword — そもそも
#エイリアスが必要だった理由。 - 学習: 式属性名と値
参考資料
- Expression attribute names (aliases) in DynamoDB — Amazon DynamoDB Developer Guide
- Query — Amazon DynamoDB API Reference
- Reserved words in DynamoDB — Amazon DynamoDB Developer Guide
最終検証日 2026-07-13、上記にリンクした公式 AWS ドキュメントに照らして確認しました。
2026-07-26 に DynamoDB Local 2.x と AWS SDK for JavaScript v3.1095.0 で再現しました — 上記の出力はそのままの逐語です。