TransactionInProgressException

TL;DR: un reintento TransactWriteItems generó el mismo ClientRequestToken que un intento que aún se está ejecutando. Este suele ser el tiempo de espera del client más rápido de lo que se completa la transacción, por lo que el reintento del SDK colisiona con el original en vuelo. Siga reintentando con retroceso (un reintento posterior después de que finalice el original devuelve el éxito idempotente) y ajuste los tiempos de espera para que al menos un reintento se realice después de ~5 segundos.

Qué significa

TransactionInProgressException: The transaction with the given request token
is already in progress.

ClientRequestToken hace que TransactWriteItems sea idempotente: las llamadas idénticas dentro de una ventana de 10 minutos cuentan como una sola transacción. Mientras el primer intento aún se procesa, una segunda llamada con el mismo token no se puede responder todavía — no es ni un duplicado de una transacción completada ni una nueva — así que DynamoDB la rechaza con esta excepción. Es una señal de temporización, no un error de datos.

Por qué ocurre

  • Tiempo de espera del cliente más corto que la latencia de la transacción — el tiempo de espera de la petición se dispara, el SDK reintenta, y el reintento llega mientras la transacción original aún se está confirmando.
  • Política de reintentos agresiva — un backoff muy corto significa que varios reintentos pueden apilarse sobre una transacción que necesita unos segundos.
  • Dos llamantes compartiendo un token — procesos separados que emiten deliberadamente (o accidentalmente) el mismo ClientRequestToken de forma concurrente.

Cómo solucionarlo

  1. Deja que los reintentos continúen con backoff exponencial — una vez que la transacción en curso se completa, un reintento con el mismo token devuelve éxito sin aplicar las escrituras dos veces. Trata esta excepción como reintentable.

  2. Ajusta los tiempos de espera según la guía documentada para que un reintento pueda aterrizar tras asentarse la transacción:

    • permite que al menos un reintento se procese tras haber transcurrido 5 segundos desde el primer intento;
    • establece el tiempo de espera por petición en aproximadamente 1 segundo o más;
    • mantén el tiempo de espera del socket ligeramente por debajo del tiempo de espera de la petición;
    • usa backoff exponencial entre intentos.
  3. No rotes el token en el reintento — generar un ClientRequestToken nuevo por intento convierte silenciosamente los reintentos en nuevas transacciones (aplicando las escrituras por duplicado). Misma intención, mismo token, durante hasta 10 minutos:

    const token = randomUUID(); // one token per logical transaction
    await client.send(new TransactWriteItemsCommand({TransactItems, ClientRequestToken: token}));
  4. Serializa los llamantes concurrentes deliberados — si dos workers pueden enviar la misma transacción lógica, haz que uno sea el propietario o enruta ambos por una cola.

  5. Registra el token y el tiempo transcurrido en cada reintento. La guía de los 5 segundos está documentada — tus logs deberían mostrar si los reintentos llegan demasiado pronto.

Ruta en DynoTable

Inspecciona los Items que toca una transacción larga antes de ajustar los tiempos de espera — ábrelos con ⌘K y confirma que no hay contención de clave caliente por parte de escritores paralelos. El área de preparación (⌘S) te permite reproducir primero una transacción más pequeña contra datos de desarrollo.

Estima el coste de escritura transaccional con la calculadora de precios. Cambia de perfil con ⌘P; Test Connection en Ajustes → Perfiles. Consulta Conectar con AWS e Instalación.

Fuentes

Errores relacionados

Referencias

Verificado por última vez el 2026-07-13 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.