medusajs/medusa · error · MedusaError

Transaction could not be found.

Error message

Transaction ${transactionId} could not be found.

What it means

TransactionOrchestrator.loadTransactionById (used by resume/cancel/retry paths) retrieves the persisted transaction by model id and transaction id from storage. If storage returns nothing, NOT_FOUND is thrown — the transaction was never checkpointed, was already cleaned up, or the ids are wrong.

Solutions

  1. Verify the transactionId and modelId exactly match what was returned when the workflow started
  2. Ensure the same workflow storage backend/instance is used across restarts (persistent Redis/DB, not memory)
  3. Check retention: if executions expire or clearExpiredExecutions purged them, the transaction is gone — restart the workflow instead of resuming

Example fix

// before
await orchestrator.resume(txId) // throws if never persisted

// after
const existing = await orchestrator.retrieveExistingTransaction(txId).catch(() => null)
if (!existing) {
  // start fresh instead of resuming
  await orchestrator.run(...)
} else {
  await orchestrator.resume(existing)
}
Defensive patterns

Strategy: try-catch

Try / catch

try { await orchestrator.resume(txId) } catch (e) { if (e.type === 'not_found' && /could not be found/.test(e.message)) { await orchestrator.run(/* fresh */) } else throw e }

Prevention

When it happens

Trigger: Calling resume/cancel/skip with a transactionId that does not exist in the configured workflow storage, or after the execution record expired/was purged, or when the storage is empty (wrong Redis DB / different storage configured than the one that ran the workflow).

Common situations: Restarting the app with a fresh/in-memory workflow storage and trying to resume pre-restart transactions; pointing at a different Redis/database than where the workflow ran; typo'd or truncated transactionId (URL decoding issues).

Related errors


AI-assisted analysis of medusajs/medusa@5e06e544a2 (2026-08-27). Data as JSON: /api/errors/bdf192b41af66735. Report an issue: GitHub.

Appendix: source

Thrown at packages/core/orchestration/src/transaction/transaction-orchestrator.ts:1786

  /** Returns an existing transaction
   * @param transactionId - unique identifier of the transaction
   * @param handler - function to handle action of the transaction
   */
  public async retrieveExistingTransaction(
    transactionId: string,
    handler: TransactionStepHandler,
    options?: { isCancelling?: boolean }
  ): Promise<DistributedTransactionType> {
    const existingTransaction =
      await TransactionOrchestrator.loadTransactionById(
        this.id,
        transactionId,
        { isCancelling: options?.isCancelling }
      )

    if (!existingTransaction) {
      throw new MedusaError(
        MedusaError.Types.NOT_FOUND,
        `Transaction ${transactionId} could not be found.`
      )
    }

    const transaction = new DistributedTransaction(
      existingTransaction.flow,
      handler,
      undefined,
      existingTransaction?.errors,
      existingTransaction?.context
    )

    return transaction
  }

  private static getStepByAction(
    flow: TransactionFlow,

View on GitHub (pinned to 5e06e544a2)