boto3: Parameter validation failed (ParamValidationError)

In breve — botocore.exceptions.ParamValidationError viene sollevata sulla tua macchina, prima che qualsiasi richiesta venga inviata — gli argomenti che hai passato non corrispondono alla forma attesa dell'operazione. Nel codice DynamoDB è quasi sempre una confusione client-vs-resource: il client di basso livello vuole DynamoDB-JSON ({'S': 'abc'}, numeri come stringhe), la resource Table vuole tipi Python nativi. Abbina lo stile all'interfaccia che stai chiamando.

Cosa 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 ogni chiamata rispetto al modello API del servizio prima di firmarla. Un fallimento qui non è un ClientError — DynamoDB non ha mai visto la richiesta — quindi except ClientError non lo intercetterà, e nessun round trip di rete è avvenuto. Il messaggio nomina l'esatto percorso del parametro che è fallito e il tipo che si aspettava.

Perché accade

  • Valori Python nativi passati al client di basso livelloboto3.client('dynamodb') parla DynamoDB JSON grezzo: ogni attributo è una mappa con tag di tipo e i valori N sono stringhe ({'N': '42'}, non 42).
  • DynamoDB-JSON passato alla resource Table — la confusione inversa: boto3.resource('dynamodb').Table(...) si aspetta valori Python semplici e fa il marshalling per te.
  • Oggetti condizione dove è attesa una stringa — il KeyConditionExpression del paginator di query accetta un'espressione stringa; gli oggetti Key('pk').eq(...) falliscono la validazione lì.
  • Un nome di parametro con refuso o non supportato — le chiavi sconosciute falliscono la validazione; un botocore obsoleto può anche rifiutare parametri aggiunti all'API dopo il suo modello incluso.

Come correggerlo

  1. Scegli un'interfaccia e usa il suo stile di tipo in modo coerente:

    # 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. Usa espressioni stringa con i paginatorKeyConditionExpression='pk = :p' più ExpressionAttributeValues, oppure pagina manualmente la resource Table con LastEvaluatedKey.

  3. Leggi il percorso del parametro nel messaggioItem.price.N ti dice esattamente quale attributo e quale tag di tipo è fallito; correggi quel singolo campo invece di indovinare.

  4. Aggiorna botocore per i fallimenti "Unknown parameter" — se il parametro è reale ma il tuo modello di validazione lo precede, pip install -U boto3 botocore.

  5. Intercettala separatamente dagli errori di servizio:

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

Scrivere a mano il DynamoDB-JSON è dove questi tag di tipo si sbagliano — il convertitore DynamoDB JSON traduce tra JSON nativo e il formato wire con tag di tipo, e l'app desktop DynoTable modifica gli Item con il marshalling gestito per te.

Errori correlati

References

Ultima verifica 2026-07-13 rispetto alla documentazione ufficiale AWS collegata sopra.

Lavora con DynamoDB senza la Console

DynoTable è un client desktop veloce per DynamoDB — sfoglia le tabelle, esegui query in stile SQL e modifica gli Item localmente.