ExpressionAttributeNames contains invalid key: Syntax error
TL;DR — 問題出在你 ExpressionAttributeNames map 左側的佔位符鍵,而非它所指向的屬性。佔位符必須是 # 後接純字母、數字或底線(#name、#p0)。若你把真實屬性名稱 — 帶著它的點、連字號、+ 號或空格 — 放進佔位符本身,DynamoDB 就會拒絕該 map。讓佔位符保持單純;把雜亂的真實名稱放在右側。
這是什麼意思
ValidationException: ExpressionAttributeNames contains invalid key:
Syntax error; key: "#my.attribute"ExpressionAttributeNames 將一個佔位符 token(用於你的 expression 內)對應到真實的屬性名稱。DynamoDB 在觸及你的資料前先驗證佔位符的語法:它必須以 # 開頭,且只包含在 expression token 內有效的字元。在 expression 文法中有意義的特殊字元 — .(路徑分隔符)、-、+、空格 — 會使佔位符本身無法解析,整個請求便以此 ValidationException 被拒絕。
為什麼會發生
- 真實屬性名稱被複製到佔位符中 — 例如
{"#stats.daily": "stats.daily"}。_鍵_中的點就是語法錯誤,不論它對應到什麼。 - 佔位符中的特殊字元 — 連字號(
#user-id)、+號或空格。#之後只有字母數字與底線是安全的。 - 缺少
#—ExpressionAttributeNames中的鍵必須以#開頭;{"name": "name"}是無效的。 - 程式庫從含有點或特殊字元的屬性名稱自動產生佔位符,將字元直接傳遞過去。
如何修正
使用簡單的佔位符並將每個對應到真實名稱:
{ ExpressionAttributeNames: {'#p0': 'user-id', '#p1': 'stats'}, KeyConditionExpression: '#p0 = :uid' }對巢狀路徑,個別為每個片段設定別名 — 每個路徑元素一個佔位符,在 expression 中以字面上的點連接:
// read stats.daily where the item has a top-level "stats" map { ProjectionExpression: '#s.#d', ExpressionAttributeNames: {'#s': 'stats', '#d': 'daily'} }注意反面情況:若屬性的_實際名稱_含有字面上的點(一個名為
"stats.daily"的屬性,而非巢狀路徑),為整個名稱用單一佔位符正是你想要的 —{'#sd': 'stats.daily'}— 讓點被視為名稱的一部分,而非路徑分隔符。檢查你的包裝器產生了什麼 — 若 ODM/輔助工具為你建立 map,記錄最終請求並檢視它產生的佔位符鍵。
處理名稱充滿點與破折號的屬性?DynoTable 桌面應用程式無論屬性叫什麼,都會自動以正確設定別名的名稱建立它的查詢。
相關錯誤
- Attribute name is a reserved keyword — 使用
ExpressionAttributeNames的另一大原因。 - Value provided in ExpressionAttributeNames unused in expressions
- Value provided in ExpressionAttributeValues unused
- 學習:Expression names & values
References
- 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 官方文件。