TransactionInProgressException

TL;DR — Un reintento de TransactWriteItems llevó el mismo ClientRequestToken que un intento que todavía se está ejecutando. Esto suele ser tu cliente agotando su tiempo más rápido de lo que la transacción se completa, así que el reintento del SDK colisiona con el original en curso. Sigue reintentando con backoff — un reintento posterior, una vez que el original termina, devuelve el éxito idempotente — y ajusta los tiempos de espera para que al menos un reintento aterrice tras ~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.

Si las transacciones tardan lo suficiente como para superar los tiempos de espera, comprueba en qué están entrando en contención — la aplicación de escritorio DynoTable te permite inspeccionar los Items implicados, y la calculadora de precios de DynamoDB muestra lo que cuesta la capacidad de escritura duplicada de las escrituras transaccionales.

Errores relacionados

References

Última verificación el 2026-07-13 con la documentación oficial de AWS enlazada arriba.

Trabaja con DynamoDB sin la Consola

DynoTable es un cliente de escritorio rápido para DynamoDB: explora tablas, ejecuta consultas estilo SQL y edita Items localmente.