DynamoDB Conditional Write mit der AWS CLI

Ein Conditional Write ist aus der Shell leicht abzuschicken und unangenehm zu lesen, weil das interessante Ergebnis eines fehlgeschlagenen Writes als Fehler statt als Ausgabe ankommt. DynamoDB Condition Expressions behandelt, was die Expression ausdrücken kann; auf dieser Seite geht es darum, eine aus der CLI auszuführen und das unterlegene Item aus dem Fehler herauszuholen.

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"}}'

Bei Erfolg gibt der Befehl nichts aus und beendet sich mit 0. War ein anderer Writer zuerst da, schlägt die Bedingung fehl und die CLI meldet die Service-Nachricht:

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

Erklärung

  • Erfolg ist still. Keine Ausgabe, Exit 0. Es gibt nichts zu parsen und nichts zu prüfen, ein Shell-Skript muss den Exit-Status also als Ergebnis behandeln. Ergänze --return-values ALL_NEW, wenn du das aktualisierte Item ausgegeben haben willst.
  • Ein Fehlschlag ist Exit-Status 254, der CLI-v2-Code für einen clientseitigen Fehler, den er sich mit einem fehlerhaft aufgebauten Request teilt. Verzweige anhand der Nachricht, bevor du wiederholst — sonst wird ein Tippfehler in deiner Expression zu einer endlosen Backoff-Schleife.
  • --return-values-on-condition-check-failure ALL_OLD funktioniert hier sehr wohl. Gültige Werte sind ALL_OLD und NONE, und es verbraucht keine Read-Kapazität. Das Item aus dem Fehler herauszubekommen kostet ein weiteres Flag, siehe unten.
  • Bedingung und Update sind getrennte Flags mit gemeinsamem Namensraum. --expression-attribute-names und --expression-attribute-values werden über --update-expression und --condition-expression hinweg zusammengeführt — deshalb laufen die generierten Namen #upd0, #cond0 durch, statt pro Klausel neu zu beginnen. Nutzt du einen Platzhalter für zwei verschiedene Bedeutungen, gewinnt stillschweigend der zweite.
  • Ein fehlgeschlagener Write wird trotzdem abgerechnet. Der Developer Guide ist eindeutig: Eine Bedingung, die zu false auswertet, verbraucht dennoch Write-Kapazität, bemessen am größeren von altem und neuem Item. Bedingungen sind keine günstige Existenzprüfung.

Die Fehlerausgabe — und wie du das Item daraus bekommst

Führe den Block einmal aus und er gelingt still. Führe ihn ein zweites Mal aus, wenn Version nicht mehr 7 ist, und aws-cli/2.36.9 gibt auf stderr aus:

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

Ergänze --return-values-on-condition-check-failure ALL_OLD und die Standardausgabe sagt dir, dass es mehr gibt, ohne es zu zeigen:

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> ist das Item, vom Standard-Text-Renderer zurückgehalten. Ergänze --cli-error-format json und das Ganze wird ausgegeben:

{
    "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"}
    }
}

(Attribut-Maps jeweils auf eine Zeile gefaltet; alles Übrige ist so, wie es ausgegeben wurde.) Version ist 8 und Genre ist gesetzt, weil der erste Lauf erfolgreich war. Das ist die Optimistic-Locking-Schleife, aus einem Shell-Skript geschlossen: leite stderr durch jq -r '.Item.Version.N', gib das als :expectedVersion zurück, wiederhole. Kein get-item und kein Fenster zwischen Lesen und Wiederholung, in das ein dritter Writer schlüpfen könnte.

Die Wiederholungen sind nicht kostenlos. Jeder abgelehnte Versuch verbraucht eine Write-Einheit, ein umkämpfter Key unter einer engen Schleife kostet also stetig, ohne voranzukommen. Der Preisrechner macht aus einer Schreibrate eine Monatssumme, falls du wissen willst, was ein Retry-Sturm wirklich kostet, bevor du die Versuche begrenzt.

Um diese Guards gegen deine eigenen Tabellen auszuführen, ohne die Platzhalter-Maps durch die Shell zu quoten, lade DynoTable herunter.

Verwandte Beispiele

Referenzen

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

Mit DynamoDB ohne die Console arbeiten

Ein schneller DynamoDB-Desktop-Client, der das echte SQL ausführt, das DynamoDB nicht kann — JOINs, GROUP BY, Aggregationen — mit visueller Bearbeitung und einem KI-Agenten auf deinen eigenen Bedrock-Schlüsseln.

30 Tage kostenlos testen, keine Kreditkarte — danach der Kostenlos-Tarif ohne Zeitlimit.