Écriture conditionnelle DynamoDB avec l'AWS CLI

Une écriture conditionnelle est simple à envoyer depuis le shell et pénible à lire, parce que le résultat intéressant — celui d'un échec — arrive sous forme d'erreur plutôt que de sortie. Les expressions de condition DynamoDB couvrent ce que l'expression peut dire ; cette page porte sur son exécution depuis la CLI et sur la récupération de l'élément perdant à partir de l'échec.

Code

aws dynamodb update-item \
  --table-name 'Music' \
  --key '{"Artist":{"S":"Arturo Sandoval"},"SongTitle":{"S":"Cubano Chant"}}' \
  --update-expression 'SET #upd0 = :updValue0, #version = :newVersion' \
  --condition-expression 'attribute_exists(#cond0) AND #version = :expectedVersion' \
  --expression-attribute-names '{"#upd0":"Genre","#version":"Version","#cond0":"Artist"}' \
  --expression-attribute-values '{":updValue0":{"S":"Latin Jazz"},":expectedVersion":{"N":"7"},":newVersion":{"N":"8"}}'

En cas de succès, la commande n'affiche rien et sort avec le code 0. Si un autre écrivain est arrivé le premier, la condition échoue et la CLI rapporte le message du service :

An error occurred (ConditionalCheckFailedException) when calling the UpdateItem operation:
The conditional request failed

Explication

  • Le succès est silencieux. Aucune sortie, code de sortie 0. Il n'y a rien à analyser et rien sur quoi s'appuyer, donc un script shell doit traiter le code de sortie comme le résultat. Ajoute --return-values ALL_NEW si tu veux que l'élément mis à jour s'affiche.
  • L'échec, c'est le code de sortie 254, celui que la CLI v2 réserve à une erreur côté client et qu'il partage avec une requête malformée. Branche sur le message avant de réessayer, sinon une faute de frappe dans ton expression devient une boucle de backoff infinie.
  • --return-values-on-condition-check-failure ALL_OLD fonctionne bel et bien ici. Les valeurs valides sont ALL_OLD et NONE, et il ne consomme aucune capacité de lecture. Extraire l'élément de l'erreur demande un flag de plus, détaillé ci-dessous.
  • La condition et la mise à jour sont des flags distincts qui partagent un espace de noms. --expression-attribute-names et --expression-attribute-values sont fusionnés entre --update-expression et --condition-expression, ce qui explique pourquoi les noms générés s'enchaînent #upd0, #cond0 au lieu de repartir de zéro à chaque clause. Réutilise un placeholder pour deux sens différents et le second l'emporte silencieusement.
  • Une écriture en échec est quand même facturée. Le Developer Guide est explicite : une condition qui s'évalue à faux consomme quand même de la capacité d'écriture, dimensionnée sur le plus gros de l'ancien et du nouvel élément. Les conditions ne sont pas un test d'existence bon marché.

La sortie d'erreur, et comment en extraire l'élément

Lance le bloc une fois et il réussit en silence. Lance-le une deuxième fois, quand Version ne vaut plus 7, et aws-cli/2.36.9 affiche sur stderr :

aws: [ERROR]: An error occurred (ConditionalCheckFailedException) when calling the UpdateItem operation: The conditional request failed

Ajoute --return-values-on-condition-check-failure ALL_OLD et la sortie par défaut t'annonce qu'il y a plus, sans le montrer :

aws: [ERROR]: An error occurred (ConditionalCheckFailedException) when calling the UpdateItem operation: The conditional request failed

Additional error details:
Item: <complex value>
Use "--cli-error-format json" or another error format to see the full details.

<complex value>, c'est l'élément, retenu par le formateur texte par défaut. Ajoute --cli-error-format json et le tout s'affiche :

{
    "Message": "The conditional request failed",
    "Code": "ConditionalCheckFailedException",
    "Item": {
        "Artist": {"S": "Arturo Sandoval"},
        "Year": {"N": "1994"},
        "Version": {"N": "8"},
        "SongTitle": {"S": "Cubano Chant"},
        "AlbumTitle": {"S": "Danzon"},
        "Genre": {"S": "Latin Jazz"}
    }
}

(Les maps d'attributs ont été repliées sur une ligne chacune ; tout le reste est tel qu'affiché.) Version vaut 8 et Genre est renseigné parce que la première exécution a réussi. Voilà la boucle de verrouillage optimiste bouclée depuis un script shell : passe stderr dans jq -r '.Item.Version.N', réinjecte la valeur comme :expectedVersion, réessaie. Pas de get-item, et aucune fenêtre entre la lecture et la reprise où un troisième écrivain pourrait se glisser.

Les reprises ne sont pas gratuites. Chaque tentative rejetée consomme une unité d'écriture : une clé disputée sous une boucle serrée facture sans relâche sans jamais avancer. Le calculateur de tarifs traduit un débit d'écriture en montant mensuel si tu veux savoir ce que coûte réellement une tempête de reprises avant de plafonner les tentatives.

Pour exécuter ces gardes sur tes propres tables sans échapper les maps de placeholders dans le shell, télécharge DynoTable.

Exemples liés

Références

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

Travaille avec DynamoDB sans la Console

Un client de bureau rapide pour DynamoDB qui exécute le vrai SQL que DynamoDB ne peut pas — JOINs, GROUP BY, agrégations — avec édition visuelle et un agent IA sur tes propres clés Bedrock.

Essai gratuit de 30 jours, sans carte bancaire — ensuite la formule Gratuit, sans limite de durée.