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"} 是無效的。
  • 程式庫從含有點或特殊字元的屬性名稱自動產生佔位符,將字元直接傳遞過去。

如何修正

  1. 使用簡單的佔位符並將每個對應到真實名稱:

    {
      ExpressionAttributeNames: {'#p0': 'user-id', '#p1': 'stats'},
      KeyConditionExpression: '#p0 = :uid'
    }
  2. 對巢狀路徑,個別為每個片段設定別名 — 每個路徑元素一個佔位符,在 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'} — 讓點被視為名稱的一部分,而非路徑分隔符。

  3. 檢查你的包裝器產生了什麼 — 若 ODM/輔助工具為你建立 map,記錄最終請求並檢視它產生的佔位符鍵。

處理名稱充滿點與破折號的屬性?DynoTable 桌面應用程式無論屬性叫什麼,都會自動以正確設定別名的名稱建立它的查詢。

相關錯誤

References

最後驗證於 2026-07-13,對照上方連結的 AWS 官方文件。

不必透過主控台就能操作 DynamoDB

DynoTable 是一款快速的 DynamoDB 桌面用戶端 — 瀏覽表格、執行 SQL 風格的查詢,並在本機編輯項目。