{"record":{"id":"cc0c9e5cc5a63087","repo":"medusajs/medusa","slug":"transactionmodel-transaction-modelid-cannot-b","errorCode":null,"errorMessage":"TransactionModel \"${transaction.modelId}\" cannot be orchestrated by \"${this.id}\" model.","messagePattern":"TransactionModel \"(.+?)\" cannot be orchestrated by \"(.+?)\" model\\.","errorType":"exception","errorClass":"MedusaError","httpStatus":null,"severity":"error","filePath":"packages/core/orchestration/src/transaction/transaction-orchestrator.ts","lineNumber":1406,"sourceCode":"    if (ret.transactionIsCancelling) {\n      await this.cancelTransaction(transaction, {\n        preventExecuteNext: true,\n      })\n    }\n\n    if (isAsync && !ret.stopExecution) {\n      // Schedule to continue the execution of async steps because they are not awaited on purpose and can be handled by another machine\n      await transaction.scheduleRetry(step, 0)\n    }\n  }\n\n  /**\n   * Start a new transaction or resume a transaction that has been previously started\n   * @param transaction - The transaction to resume\n   */\n  public async resume(transaction: DistributedTransactionType): Promise<void> {\n    if (transaction.modelId !== this.id) {\n      throw new MedusaError(\n        MedusaError.Types.NOT_ALLOWED,\n        `TransactionModel \"${transaction.modelId}\" cannot be orchestrated by \"${this.id}\" model.`\n      )\n    }\n\n    if (transaction.hasFinished()) {\n      return\n    }\n\n    const executeNext = async () => {\n      const flow = transaction.getFlow()\n\n      if (flow.state === TransactionState.NOT_STARTED) {\n        flow.state = TransactionState.INVOKING\n        flow.startedAt = Date.now()\n\n        await transaction.saveCheckpoint({\n          ttl: flow.hasAsyncSteps ? 0 : TransactionOrchestrator.DEFAULT_TTL,","sourceCodeStart":1388,"sourceCodeEnd":1424,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/core/orchestration/src/transaction/transaction-orchestrator.ts#L1388-L1424","documentation":"TransactionOrchestrator.resume(transaction) can only resume transactions that belong to the same workflow model. Every DistributedTransaction carries the modelId of the flow definition it was created from; resuming with an orchestrator whose id differs throws NOT_ALLOWED to prevent applying the wrong flow to saved state.","triggerScenarios":"Calling orchestratorA.resume(transactionB) where transactionB.modelId !== orchestratorA.id — e.g. loading a transaction from storage with one workflow's orchestrator and resuming it with another, or resuming after renaming a workflow's id.","commonSituations":"Renaming a workflow (its id) while old transactions still exist in storage; sharing a storage across multiple workflow engines and mixing up orchestrator instances; code that fetches 'any' transaction and resumes it generically.","solutions":["Resume with the orchestrator whose workflow id matches transaction.modelId","If a workflow was renamed, use the old orchestrator (or same id) to resume in-flight transactions, then migrate","Filter by modelId when loading transactions from storage before resuming"],"exampleFix":"// before\nawait someOtherOrchestrator.resume(loadedTx)\n\n// after\nif (loadedTx.modelId === orchestrator.id) {\n  await orchestrator.resume(loadedTx)\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"const canResume = (orchestrator, tx) =>\n  tx.modelId === orchestrator.id && !tx.hasFinished()","tryCatchPattern":"try { await orchestrator.resume(tx) } catch (e) { if (e.type === 'not_allowed' && /cannot be orchestrated/.test(e.message)) { /* route to correct orchestrator */ } throw e }","preventionTips":["Never rename workflow ids while transactions are in flight","Always pair a loaded transaction with the orchestrator of the same model id"],"tags":["orchestration","workflow","resume","model-mismatch"],"backgroundTag":"workflow-model-mismatch","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}