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 值傳給低階 client —
boto3.client('dynamodb')說的是原始 DynamoDB JSON:每個屬性都是帶型別標記的 map,而N值是_字串_({'N': '42'},不是42)。 - 把 DynamoDB-JSON 傳給
Tableresource — 反過來的混用:boto3.resource('dynamodb').Table(...)預期單純的 Python 值,並且會替你處理 marshalling。 - 在預期字串的位置給了 Condition 物件 — query 分頁器的
KeyConditionExpression接受字串運算式;Key('pk').eq(...)物件在那裡會驗證失敗。 - 參數名稱打錯或不支援 — 未知的鍵會驗證失敗;過舊的 botocore 也可能拒絕那些在它內建模型之後才加進 API 的參數。
如何修正
選定一個介面,並一致地使用它的型別風格:
# 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'}})搭配分頁器時使用字串運算式 —
KeyConditionExpression='pk = :p'加上ExpressionAttributeValues,或用LastEvaluatedKey手動為Tableresource 分頁。讀訊息中的參數路徑 —
Item.price.N精確告訴你是哪個屬性、哪個型別標記失敗;修那一個欄位,不要用猜的。遇到「Unknown parameter」失敗就升級 botocore — 如果參數確實存在,只是你的驗證模型比它更舊,執行
pip install -U boto3 botocore。與服務錯誤分開捕捉:
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,所以沒有消耗容量,也沒有東西可重試;修正處永遠在呼叫端。
相關錯誤
- Float types are not supported — boto3 另一種用戶端型別拒絕(改用
Decimal)。 - ValidationException: One or more parameter values were invalid — 請求真的送出去之後,伺服器端的對應錯誤。
- 學習:DynamoDB JSON 與 marshalling
參考資料
- Error handling — Boto3 documentation
- AttributeValue — Amazon DynamoDB API Reference
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
最後於 2026-07-13 對照上方連結的官方 AWS 文件驗證。
已於 2026-07-26 對照 boto3 1.43.56/botocore 1.43.56 重現 — 上方輸出為逐字原文。