boto3: Parameter validation failed (ParamValidationError)
TL;DR — botocore.exceptions.ParamValidationError se lanza en tu máquina, antes de que se envíe cualquier solicitud — los argumentos que pasaste no coinciden con la forma esperada de la operación. En código de DynamoDB casi siempre es una confusión entre client y resource: el client de bajo nivel quiere DynamoDB-JSON ({'S': 'abc'}, números como cadenas), el resource Table quiere tipos nativos de Python. Ajusta el estilo a la interfaz que estás llamando.
Qué significa
botocore.exceptions.ParamValidationError: Parameter validation failed:
Invalid type for parameter Item.price.N, value: 42, type: <class 'int'>,
valid types: <class 'str'>botocore valida cada llamada contra el modelo de API del servicio antes de firmarla. Un fallo aquí no es un ClientError — DynamoDB nunca vio la solicitud — así que except ClientError no lo capturará, y no ocurrió ningún viaje de red. El mensaje nombra la ruta exacta del parámetro que falló y el tipo que esperaba.
Por qué ocurre
- Valores nativos de Python pasados al client de bajo nivel —
boto3.client('dynamodb')habla DynamoDB JSON crudo: cada atributo es un mapa etiquetado por tipo y los valoresNson cadenas ({'N': '42'}, no42). - DynamoDB-JSON pasado al resource
Table— la confusión inversa:boto3.resource('dynamodb').Table(...)espera valores planos de Python y hace el marshalling por ti. - Objetos de condición donde se espera una cadena — el
KeyConditionExpressiondel paginador de query acepta una expresión de cadena; los objetosKey('pk').eq(...)fallan la validación ahí. - Un nombre de parámetro con errata o no soportado — las claves desconocidas fallan la validación; un botocore desactualizado también puede rechazar parámetros añadidos a la API después de su modelo empaquetado.
Cómo solucionarlo
Elige una interfaz y usa su estilo de tipos de forma consistente:
# 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'}})Usa expresiones de cadena con los paginadores —
KeyConditionExpression='pk = :p'másExpressionAttributeValues, o pagina el resourceTablemanualmente conLastEvaluatedKey.Lee la ruta del parámetro en el mensaje —
Item.price.Nte dice exactamente qué atributo y qué etiqueta de tipo falló; arregla ese campo en lugar de adivinar.Actualiza botocore para los fallos "Unknown parameter" — si el parámetro es real pero tu modelo de validación es anterior a él,
pip install -U boto3 botocore.Captúralo por separado de los errores de servicio:
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 ...
Escribir DynamoDB-JSON a mano es donde estas etiquetas de tipo se tuercen — el conversor de DynamoDB JSON traduce entre JSON nativo y el formato de cable etiquetado por tipo, y la app de escritorio DynoTable edita Items con el marshalling gestionado por ti.
Errores relacionados
- Float types are not supported — el otro rechazo de tipo del lado del cliente de boto3 (usa
Decimal). - ValidationException: One or more parameter values were invalid — la contraparte del lado del servidor una vez que la solicitud sí sale.
- Aprende: DynamoDB JSON & marshalling
Referencias
- Error handling — Boto3 documentation
- AttributeValue — Amazon DynamoDB API Reference
- Error handling with DynamoDB — Amazon DynamoDB Developer Guide
Verificado por última vez el 2026-07-13 contra la documentación oficial de AWS enlazada arriba.