Escritura condicional en DynamoDB con la AWS CLI

Una escritura condicional es sencilla de enviar desde la shell e incómoda de leer, porque el resultado interesante de una que falla llega como error en lugar de como salida. Las expresiones de condición de DynamoDB cubren qué puede expresar la condición; esta página trata de ejecutar una desde la CLI y sacar del error el Item que perdió la carrera.

Código

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

Si tiene éxito, el comando no imprime nada y sale con 0. Si otro escritor llegó antes, la condición falla y la CLI informa del mensaje del servicio:

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

Explicación

  • El éxito es silencioso. Sin salida, código 0. No hay nada que parsear ni sobre lo que aseverar, así que un script de shell tiene que tratar el estado de salida como el resultado. Añade --return-values ALL_NEW si quieres que imprima el Item actualizado.
  • El fallo es el estado de salida 254, que es el código de la CLI v2 para un error del lado del cliente y lo comparte con una petición mal formada. Ramifica según el mensaje antes de reintentar, o una errata en tu expresión se convierte en un bucle de backoff infinito.
  • --return-values-on-condition-check-failure ALL_OLD sí funciona aquí. Los valores válidos son ALL_OLD y NONE, y no consume capacidad de lectura. Sacar el Item del error cuesta un flag más, que se explica abajo.
  • La condición y la actualización son flags separados con un espacio de nombres compartido. --expression-attribute-names y --expression-attribute-values se fusionan entre --update-expression y --condition-expression, y por eso los nombres generados van #upd0, #cond0 en vez de reiniciarse por cláusula. Reutiliza un marcador de posición para dos significados distintos y el segundo gana en silencio.
  • Una escritura fallida también se factura. La Developer Guide es explícita: una condición que se evalúa como falsa consume capacidad de escritura igualmente, dimensionada según el mayor entre el Item antiguo y el nuevo. Las condiciones no son una sonda de existencia barata.

La salida de error, y cómo sacar el Item de ella

Ejecuta el bloque una vez y tiene éxito en silencio. Ejecútalo una segunda vez, cuando Version ya no es 7, y aws-cli/2.36.9 imprime en stderr:

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

Añade --return-values-on-condition-check-failure ALL_OLD y la salida por defecto te dice que hay más, sin mostrarlo:

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> es el Item, retenido por el renderizador de texto por defecto. Añade --cli-error-format json y se imprime entero:

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

(Los mapas de atributos están plegados a una línea cada uno; todo lo demás es tal cual se imprime.) Version es 8 y Genre está puesto porque la primera ejecución tuvo éxito. Ese es el bucle de bloqueo optimista cerrado desde un script de shell: canaliza stderr por jq -r '.Item.Version.N', devuélvelo como :expectedVersion y reintenta. Sin get-item, y sin ventana entre la lectura y el reintento para que se cuele un tercer escritor.

Los reintentos no son gratis. Cada intento rechazado consume una unidad de escritura, así que una clave disputada bajo un bucle cerrado factura sin parar mientras no avanza. La calculadora de precios convierte una tasa de escritura en una cifra mensual si quieres saber cuánto cuesta de verdad una tormenta de reintentos antes de limitar los intentos.

Para ejecutar estas guardas contra tus propias tablas sin escapar los mapas de marcadores en la shell, descarga DynoTable.

Ejemplos relacionados

Referencias

Verificado por última vez el 2026-07-28 contra la documentación oficial de AWS enlazada arriba.

Trabaja con DynamoDB sin la Consola

Un cliente de escritorio rápido para DynamoDB que ejecuta el SQL real que DynamoDB no puede — JOINs, GROUP BY, agregaciones — con edición visual y un agente de IA con tus propias claves de Bedrock.

Prueba gratuita de 30 días, sin tarjeta — después, el plan Free sin límite de tiempo.