boto3: Parameter validation failed (ParamValidationError)

TL;DR — botocore.exceptions.ParamValidationError é lançado na sua máquina, antes de qualquer requisição ser enviada — os argumentos que você passou não correspondem à forma esperada da operação. Em código de DynamoDB é quase sempre uma confusão client-vs-resource: o client de baixo nível quer DynamoDB-JSON ({'S': 'abc'}, números como strings), o resource Table quer tipos Python nativos. Combine o estilo com a interface que você está chamando.

O que significa

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

O botocore valida toda chamada contra o modelo de API do serviço antes de assiná-la. Uma falha aqui não é um ClientError — o DynamoDB nunca viu a requisição — então except ClientError não a capturará, e nenhum round trip de rede aconteceu. A mensagem nomeia o caminho de parâmetro exato que falhou e o tipo que ele esperava.

Por que acontece

  • Valores Python nativos passados ao cliente de baixo nívelboto3.client('dynamodb') fala DynamoDB JSON cru: todo atributo é um map com tag de tipo e valores N são strings ({'N': '42'}, não 42).
  • DynamoDB-JSON passado ao resource Table — a confusão inversa: boto3.resource('dynamodb').Table(...) espera valores Python simples e faz o marshalling por você.
  • Objetos de condição onde uma string é esperada — o KeyConditionExpression do paginator de query aceita uma expressão de string; objetos Key('pk').eq(...) falham na validação ali.
  • Um nome de parâmetro com erro de digitação ou não suportado — chaves desconhecidas falham na validação; um botocore desatualizado também pode rejeitar parâmetros adicionados à API depois de seu modelo empacotado.

Como corrigir

  1. Escolha uma interface e use seu estilo de tipo consistentemente:

    # 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. Use expressões de string com paginatorsKeyConditionExpression='pk = :p' mais ExpressionAttributeValues, ou pagine o resource Table manualmente com LastEvaluatedKey.

  3. Leia o caminho de parâmetro na mensagemItem.price.N te diz exatamente qual atributo e qual tag de tipo falhou; corrija esse campo em vez de adivinhar.

  4. Atualize o botocore para falhas de "Unknown parameter" — se o parâmetro é real mas seu modelo de validação o antecede, pip install -U boto3 botocore.

  5. Capture-o separadamente de erros de serviço:

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

Escrever DynamoDB-JSON à mão é onde essas tags de tipo dão errado — o conversor de DynamoDB JSON traduz entre JSON nativo e o formato de fio com tags de tipo, e o app desktop DynoTable edita itens com o marshalling tratado por você.

Erros relacionados

Referências

Verificado pela última vez em 2026-07-13 contra a documentação oficial da AWS vinculada acima.

Trabalhe com o DynamoDB sem o Console

O DynoTable é um cliente desktop rápido para o DynamoDB — navegue pelas tabelas, execute consultas no estilo SQL e edite itens localmente.