{"record":{"id":"b095c5ae861f9b35","repo":"medusajs/medusa","slug":"unable-to-serialize-context-object-please-make-su","errorCode":null,"errorMessage":"Unable to serialize context object. Please make sure the workflow input and steps response are serializable.","messagePattern":"Unable to serialize context object\\. Please make sure the workflow input and steps response are serializable\\.","errorType":"exception","errorClass":"NonSerializableCheckPointError","httpStatus":null,"severity":"error","filePath":"packages/core/orchestration/src/transaction/distributed-transaction.ts","lineNumber":710,"sourceCode":"  }\n\n  public hasTemporaryData(key: string) {\n    return this.#temporaryStorage.has(key)\n  }\n\n  /**\n   * Try to serialize the checkpoint data\n   * If it fails, it means that the context or the errors are not serializable\n   * and we should handle it\n   *\n   * @internal\n   * @returns\n   */\n  #serializeCheckpointData() {\n    try {\n      JSON.stringify(this.context)\n    } catch {\n      throw new NonSerializableCheckPointError(\n        \"Unable to serialize context object. Please make sure the workflow input and steps response are serializable.\"\n      )\n    }\n\n    let errorsToUse = this.getErrors()\n    try {\n      JSON.stringify(errorsToUse)\n    } catch {\n      // Sanitize non-serializable errors\n      const sanitizedErrors: TransactionStepError[] = []\n      for (const error of this.errors) {\n        try {\n          JSON.stringify(error)\n          sanitizedErrors.push(error)\n        } catch {\n          sanitizedErrors.push({\n            action: error.action,\n            handlerType: error.handlerType,","sourceCodeStart":692,"sourceCodeEnd":728,"githubUrl":"https://github.com/medusajs/medusa/blob/5e06e544a296b9033f20f71f11c559f81a0e5739/packages/core/orchestration/src/transaction/distributed-transaction.ts#L692-L728","documentation":"When a workflow checkpoints itself (long-running/async workflows that save state between steps), DistributedTransaction must serialize its whole context (workflow input plus every step response) to JSON for storage. If any value in that context is not serializable (BigInt, circular reference, class with toJSON that throws, etc.), NonSerializableCheckPointError is thrown so the state is not silently corrupted.","triggerScenarios":"Calling saveCheckpoint (explicitly, or automatically when a workflow suspends with .requestTimeout/waitFor or when the engine checkpoints after each step) while the workflow input or a step's response contains a non-JSON-serializable value such as BigInt, a circular object graph, or a function/Symbol-bearing payload.","commonSituations":"Passing ORM entities, Map/Set, or IDs as BigInt into workflows; a step returning a model instance with circular relations; enabling async/checkpointed workflows on data that previously only flowed in-memory.","solutions":["Sanitize the workflow input: convert BigInt to string, replace Map/Set with arrays/objects before running the workflow","Make step responses return plain serializable DTOs instead of entity instances","If you need dates/BigInt, convert at the boundary (e.g. value.toString()) and reconstruct in later steps","Test your workflow input with JSON.stringify before invoking it"],"exampleFix":"// before\nconst input = { productId: 123n } // BigInt → serialization fails on checkpoint\nawait myWorkflow(req.scope).run({ input })\n\n// after\nconst input = { productId: \"123\" } // string survives JSON checkpointing\nawait myWorkflow(req.scope).run({ input })","handlingStrategy":"validation","validationCode":"// Validate workflow input is JSON-safe before running a checkpointable workflow\nfunction assertSerializable(obj, seen = new WeakSet()) {\n  if (obj === null || typeof obj !== 'object') {\n    if (typeof obj === 'bigint') throw new Error('BigInt not serializable')\n    return\n  }\n  if (seen.has(obj)) throw new Error('Circular reference')\n  seen.add(obj)\n  for (const v of Object.values(obj)) assertSerializable(v, seen)\n}\nassertSerializable(input)\nawait myWorkflow(container).run({ input })","typeGuard":null,"tryCatchPattern":"try { await workflow.run({ input }) } catch (e) { if (e.name === 'NonSerializableCheckPointError') { /* sanitize input: String(bigints), strip entities, rerun */ } throw e }","preventionTips":["Pass plain DTOs/primitives into workflows, never ORM entities or class instances","Convert BigInt ids to strings at API boundaries","Unit-test JSON.stringify(input) for every workflow input shape in CI"],"tags":["orchestration","workflow","serialization","checkpoint"],"backgroundTag":"non-serializable-workflow-data","analyzedSha":"5e06e544a296b9033f20f71f11c559f81a0e5739","analyzedAt":"2026-08-27T07:24:39.599Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}