{"record":{"id":"8f681fe6ea2c804d","repo":"mastra-ai/mastra","slug":"httpremotestrategy-requestcontext-is-not-json-ser","errorCode":null,"errorMessage":"HttpRemoteStrategy: requestContext is not JSON-serializable. ${err instanceof Error ? err.message : String(err)}","messagePattern":"HttpRemoteStrategy: requestContext is not JSON-serializable\\. (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/core/src/worker/strategies/http-remote-strategy.ts","lineNumber":99,"sourceCode":"\n    return res.json() as Promise<StepResult<unknown, unknown, unknown, unknown>>;\n  }\n\n  /**\n   * Build a JSON-serializable request body. The `params.requestContext` is\n   * a plain object; if a caller stuffed a non-serializable value into it we\n   * surface a clear error instead of silently dropping fields.\n   *\n   * `abortSignal` is consumed via fetch's `signal` argument — it must not\n   * be in the body.\n   */\n  #buildBody(params: StepExecutionParams): string {\n    const { abortSignal: _abortSignal, requestContext, ...rest } = params;\n    let safeRequestContext: Record<string, unknown>;\n    try {\n      safeRequestContext = JSON.parse(JSON.stringify(requestContext ?? {}));\n    } catch (err) {\n      throw new Error(\n        `HttpRemoteStrategy: requestContext is not JSON-serializable. ${err instanceof Error ? err.message : String(err)}`,\n      );\n    }\n\n    return JSON.stringify({\n      ...rest,\n      requestContext: safeRequestContext,\n    });\n  }\n\n  #combineSignals(externalSignal?: AbortSignal): AbortSignal {\n    const timeoutSignal = AbortSignal.timeout(this.#timeoutMs);\n    if (!externalSignal) return timeoutSignal;\n    // AbortSignal.any aborts when any input aborts.\n    if (typeof AbortSignal.any === 'function') {\n      return AbortSignal.any([timeoutSignal, externalSignal]);\n    }\n    // Fallback for runtimes without AbortSignal.any","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/worker/strategies/http-remote-strategy.ts#L81-L117","documentation":"Before POSTing step params, #buildBody round-trips requestContext through JSON.parse(JSON.stringify(...)) to guarantee a plain serializable payload. If requestContext contains non-JSON values (functions, class instances with circular refs, BigInt, undefined in hostile spots), serialization throws and this descriptive error replaces the opaque JSON error.","triggerScenarios":"Storing a function, class instance, Map/Set, circular object graph, or BigInt in requestContext before executing a step via HttpRemoteStrategy.","commonSituations":"Passing a logger, DB client, or Prisma client via requestContext; putting the raw Hono/Express request object into context; using context values that worked locally with InProcessStrategy but break over HTTP.","solutions":["Ensure requestContext holds only JSON-safe values (strings, numbers, plain objects, arrays)","Remove non-serializable members (clients, loggers, functions) before invoking the step","Convert special types explicitly (BigInt -> string, Date -> ISO string, Map -> Object.fromEntries)"],"exampleFix":"// before\nrequestContext.set('db', prisma);\n// after\nrequestContext.set('dbConnectionString', process.env.DATABASE_URL);","handlingStrategy":"type-guard","validationCode":"function isJsonSafe(v: unknown, seen = new Set()): boolean {\n  if (v === null || typeof v !== 'object') return typeof v !== 'function' && typeof v !== 'bigint';\n  if (seen.has(v)) return false;\n  seen.add(v);\n  return Object.values(v).every((x) => isJsonSafe(x, seen));\n}","typeGuard":null,"tryCatchPattern":"try {\n  await strategy.executeStep(params);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('not JSON-serializable')) {\n    console.error('requestContext contains non-JSON values:', e.message);\n  }\n  throw e;\n}","preventionTips":["Keep requestContext limited to plain JSON data","Never place clients, loggers, or request objects in requestContext","Convert Date/Map/BigInt values explicitly before passing them","Test with InProcessStrategy early, but validate serializability before HTTP execution"],"tags":["serialization","worker","http","request-context"],"backgroundTag":"circular-reference-serialization","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}