boto3: Parameter validation failed (ParamValidationError)

TL;DR — botocore.exceptions.ParamValidationError wird auf deiner Maschine ausgelöst, bevor irgendeine Anfrage gesendet wird — die von dir übergebenen Argumente passen nicht zur erwarteten Form der Operation. In DynamoDB-Code ist es fast immer eine Client-vs-Resource-Verwechslung: der Low-Level-client will DynamoDB-JSON ({'S': 'abc'}, Zahlen als Zeichenketten), die Table-Resource will native Python-Typen. Passe den Stil an die Schnittstelle an, die du aufrufst.

Was es bedeutet

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

botocore validiert jeden Aufruf gegen das API-Modell des Dienstes, bevor es ihn signiert. Ein Fehler hier ist kein ClientError — DynamoDB hat die Anfrage nie gesehen —, also fängt except ClientError ihn nicht ab, und es fand kein Netzwerk-Roundtrip statt. Die Meldung benennt den genauen Parameterpfad, der fehlgeschlagen ist, und den Typ, den er erwartet hat.

Warum es passiert

  • Native Python-Werte an den Low-Level-Client übergebenboto3.client('dynamodb') spricht rohes DynamoDB-JSON: jedes Attribut ist eine typmarkierte Map und N-Werte sind Zeichenketten ({'N': '42'}, nicht 42).
  • DynamoDB-JSON an die Table-Resource übergeben — die umgekehrte Verwechslung: boto3.resource('dynamodb').Table(...) erwartet einfache Python-Werte und übernimmt das Marshalling für dich.
  • Condition-Objekte, wo eine Zeichenkette erwartet wird — der KeyConditionExpression des Query-Paginators akzeptiert einen String-Ausdruck; Key('pk').eq(...)-Objekte scheitern dort an der Validierung.
  • Ein vertippter oder nicht unterstützter Parametername — unbekannte Schlüssel scheitern an der Validierung; ein veraltetes botocore kann außerdem Parameter ablehnen, die der API nach seinem gebündelten Modell hinzugefügt wurden.

So behebst du es

  1. Wähle eine Schnittstelle und nutze ihren Typstil konsistent:

    # 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. Nutze String-Ausdrücke mit PaginatorenKeyConditionExpression='pk = :p' plus ExpressionAttributeValues, oder paginiere die Table-Resource manuell mit LastEvaluatedKey.

  3. Lies den Parameterpfad in der MeldungItem.price.N sagt dir genau, welches Attribut und welches Typ-Tag fehlgeschlagen ist; behebe genau dieses eine Feld, statt zu raten.

  4. Aktualisiere botocore bei "Unknown parameter"-Fehlern — wenn der Parameter echt ist, dein Validierungsmodell ihm aber vorausgeht, pip install -U boto3 botocore.

  5. Fange ihn getrennt von Service-Fehlern ab:

    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 von Hand zu schreiben ist der Ort, an dem diese Typ-Tags schiefgehen — der DynamoDB-JSON-Konverter übersetzt zwischen nativem JSON und dem typmarkierten Wire-Format, und die DynoTable-Desktop-App bearbeitet Items mit erledigtem Marshalling für dich.

Verwandte Fehler

References

Zuletzt verifiziert am 2026-07-13 gegen die oben verlinkte offizielle AWS-Dokumentation.

Mit DynamoDB ohne die Console arbeiten

DynoTable ist ein schneller Desktop-Client für DynamoDB — durchsuche Tabellen, führe SQL-artige Queries aus und bearbeite Items lokal.