boto3: Parameter validation failed (ParamValidationError)
TL;DR — botocore.exceptions.ParamValidationError は、リクエストが送信される前に自分のマシン上で発生します — 渡した引数が、その操作の期待するシェイプと一致していません。DynamoDB のコードでは、ほぼ必ず client と resource の取り違えです。低レベルの client は DynamoDB JSON({'S': 'abc'}、数値は文字列)を求め、Table リソースはネイティブの 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 では捕まえられず、ネットワークのラウンドトリップも発生していません。メッセージは、失敗した正確なパラメータのパスと、期待していた型を名指しします。
発生する理由
- 低レベルの client にネイティブの Python 値を渡している —
boto3.client('dynamodb')は生の DynamoDB JSON を話します。すべての属性は型タグ付きのマップで、Nの値は 文字列 です(42ではなく{'N': '42'})。 Tableリソースに DynamoDB JSON を渡している — 逆の取り違えです。boto3.resource('dynamodb').Table(...)はプレーンな Python の値を期待し、マーシャリングを代わりに行います。- 文字列が期待される場所に Condition オブジェクト — クエリのページネーターの
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'}})ページネーターでは文字列の式を使います —
KeyConditionExpression='pk = :p'とExpressionAttributeValuesの組み合わせにするか、LastEvaluatedKeyを使ってTableリソースを手動でページングします。メッセージ中のパラメータのパスを読みます —
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 デスクトップアプリはマーシャリングを引き受けたうえでアイテムを編集させてくれます。
再現方法
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 は、パラメータ、受け取った値、その型、そして期待した型を名指しします — 1つのメッセージに4つの事実です。AWS には何も送信されていないので、キャパシティは消費されず、リトライすべきものもありません。修正は常に呼び出し側にあります。
関連するエラー
- Float types are not supported — boto3 のもう1つのクライアント側の型拒否(
Decimalを使いましょう)。 - ValidationException: One or more parameter values were invalid — リクエストが実際に送られた後の、サーバー側の対応物。
- 学習: DynamoDB JSON とマーシャリング
参考資料
- 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 で再現しました — 上記の出力はそのままの逐語です。