boto3 : Parameter validation failed (ParamValidationError)

En bref — botocore.exceptions.ParamValidationError est levée sur ta machine, avant l'envoi de toute requête — les arguments que tu as passés ne correspondent pas à la forme attendue de l'opération. Dans du code DynamoDB, c'est presque toujours une confusion client-vs-resource : le client de bas niveau veut du DynamoDB-JSON ({'S': 'abc'}, nombres sous forme de chaînes), la resource Table veut des types Python natifs. Adapte le style à l'interface que tu appelles.

Ce que ça signifie

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

botocore valide chaque appel par rapport au modèle d'API du service avant de le signer. Un échec ici n'est pas une ClientError — DynamoDB n'a jamais vu la requête — donc except ClientError ne l'attrapera pas, et aucun aller-retour réseau n'a eu lieu. Le message nomme le chemin exact du paramètre qui a échoué et le type qu'il attendait.

Pourquoi ça arrive

  • Des valeurs Python natives passées au client de bas niveauboto3.client('dynamodb') parle le DynamoDB JSON brut : chaque attribut est une map typée et les valeurs N sont des chaînes ({'N': '42'}, pas 42).
  • Du DynamoDB-JSON passé à la resource Table — la confusion inverse : boto3.resource('dynamodb').Table(...) attend des valeurs Python simples et fait le marshalling pour toi.
  • Des objets Condition là où une chaîne est attendue — le KeyConditionExpression du paginateur de Query accepte une expression sous forme de chaîne ; les objets Key('pk').eq(...) échouent à la validation à cet endroit.
  • Un nom de paramètre erroné ou non pris en charge — les clés inconnues échouent à la validation ; un botocore obsolète peut aussi rejeter des paramètres ajoutés à l'API après son modèle embarqué.

Comment le corriger

  1. Choisis une interface et utilise son style de types de façon cohérente :

    # 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. Utilise des expressions sous forme de chaînes avec les paginateursKeyConditionExpression='pk = :p' plus ExpressionAttributeValues, ou paginate la resource Table manuellement avec LastEvaluatedKey.

  3. Lis le chemin du paramètre dans le messageItem.price.N t'indique exactement quel attribut et quelle balise de type ont échoué ; corrige ce champ précis plutôt que de deviner.

  4. Mets à jour botocore pour les échecs « Unknown parameter » — si le paramètre est réel mais que ton modèle de validation le précède, pip install -U boto3 botocore.

  5. Attrape-la séparément des erreurs de service :

    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
        ...

Écrire du DynamoDB-JSON à la main est là où ces balises de type tournent mal — le convertisseur DynamoDB JSON traduit entre le JSON natif et le format filaire typé, et l'application de bureau DynoTable édite les éléments avec le marshalling géré pour toi.

Erreurs liées

Références

Dernière vérification le 2026-07-13 par rapport à la documentation officielle AWS liée ci-dessus.

Travaille avec DynamoDB sans la Console

DynoTable est un client de bureau rapide pour DynamoDB — parcours les tables, exécute des requêtes de style SQL et édite les items en local.