boto3:Parameter validation failed(ParamValidationError)

TL;DR — botocore.exceptions.ParamValidationError 是在你自己的機器上拋出的,發生在任何請求送出之前 — 你傳入的引數與該操作預期的結構不符。在 DynamoDB 程式碼中,這幾乎總是 client 與 resource 的混用:低階的 client 要的是 DynamoDB-JSON({'S': 'abc'},數字用字串表示),而 Table resource 要的是原生 Python 型別。讓型別風格與你呼叫的介面一致。

這是什麼意思

botocore.exceptions.ParamValidationError: Parameter validation failed:
Invalid type for parameter Item.price.N, value: 42, type: <class 'int'>,
valid types: <class 'str'>

# what the engine actually returns, reproduced against boto3 1.43.67 on Python 3.11.15:
ParamValidationError: Parameter validation failed:
Invalid type for parameter Item.price.N, value: 42, type: <class 'int'>, valid types: <class 'str'>

botocore 會在簽署之前,先拿服務的 API 模型驗證每一次呼叫。這裡的失敗不是 ClientError — DynamoDB 從未看到這個請求 — 所以 except ClientError 捕捉不到它,也沒有任何網路往返發生。訊息會指出失敗的確切參數路徑,以及它預期的型別。

為什麼會發生

  • 把原生 Python 值傳給低階 clientboto3.client('dynamodb') 說的是原始 DynamoDB JSON:每個屬性都是帶型別標記的 map,而 N 值是_字串_({'N': '42'},不是 42)。
  • 把 DynamoDB-JSON 傳給 Table resource — 反過來的混用:boto3.resource('dynamodb').Table(...) 預期單純的 Python 值,並且會替你處理 marshalling。
  • 在預期字串的位置給了 Condition 物件 — query 分頁器的 KeyConditionExpression 接受字串運算式;Key('pk').eq(...) 物件在那裡會驗證失敗。
  • 參數名稱打錯或不支援 — 未知的鍵會驗證失敗;過舊的 botocore 也可能拒絕那些在它內建模型之後才加進 API 的參數。

如何修正

  1. 選定一個介面,並一致地使用它的型別風格:

    # Table resource — native Python types
    table = boto3.resource('dynamodb').Table('orders')
    table.put_item(Item={'pk': 'ORDER#1', 'price': Decimal('42')})
    
    # Low-level client — DynamoDB-JSON, numbers as strings
    client = boto3.client('dynamodb')
    client.put_item(TableName='orders',
                    Item={'pk': {'S': 'ORDER#1'}, 'price': {'N': '42'}})
  2. 搭配分頁器時使用字串運算式KeyConditionExpression='pk = :p' 加上 ExpressionAttributeValues,或用 LastEvaluatedKey 手動為 Table resource 分頁。

  3. 讀訊息中的參數路徑Item.price.N 精確告訴你是哪個屬性、哪個型別標記失敗;修那一個欄位,不要用猜的。

  4. 遇到「Unknown parameter」失敗就升級 botocore — 如果參數確實存在,只是你的驗證模型比它更舊,執行 pip install -U boto3 botocore

  5. 與服務錯誤分開捕捉:

    from botocore.exceptions import ClientError, ParamValidationError
    try:
        client.put_item(**kwargs)
    except ParamValidationError as e:   # local: fix the call
        ...
    except ClientError as e:            # remote: DynamoDB rejected it
        ...

手寫 DynamoDB-JSON 正是這些型別標記出錯的地方 — DynamoDB JSON 轉換器可在原生 JSON 與帶型別標記的傳輸格式之間轉換,而 DynoTable 桌面應用程式在編輯項目時會替你處理 marshalling。

重現方式

在 boto3 預期 Key 對應表的位置傳一個字串。這個檢查完全在用戶端進行:

import boto3
boto3.client('dynamodb', region_name='us-east-1').get_item(TableName='repro', Key='not-a-dict')

實際輸出:

ParamValidationError: Parameter validation failed:
Invalid type for parameter Key, value: not-a-dict, type: <class 'str'>, valid types: <class 'dict'>

botocore 一則訊息裡就給了四項事實:參數名稱、它收到的值、該值的型別,以及它想要的型別。什麼都沒送到 AWS,所以沒有消耗容量,也沒有東西可重試;修正處永遠在呼叫端。

相關錯誤

參考資料

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

已於 2026-07-26 對照 boto3 1.43.56/botocore 1.43.56 重現 — 上方輸出為逐字原文。

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

一款快速的 DynamoDB 桌面用戶端,可執行 DynamoDB 無法執行的真正 SQL — JOINs、GROUP BY、聚合 — 並支援視覺化編輯與使用你自己的 Bedrock 金鑰的 AI 代理。

30 天免費試用,無需信用卡 — 之後為無時間限制的免費方案。