{"record":{"id":"37781d6d9b5ea3da","repo":"mastra-ai/mastra","slug":"describebadplaceholder-template-idx-rawexpr-37781d","errorCode":null,"errorMessage":"${describeBadPlaceholder(template, idx, rawExpr)} resolved to a value that could not be JSON-stringified (${(err as Error).message}). Drill into a primitive path (e.g. ${${rawExpr}.someField}) or reshape the value in a preceding step.","messagePattern":"(.+?) resolved to a value that could not be JSON-stringified \\((.+?)\\)\\. Drill into a primitive path \\(e\\.g\\. (.+?)\\.someField\\}\\) or reshape the value in a preceding step\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/workflows/mapping-template.ts","lineNumber":123,"sourceCode":"  }\n  return ids;\n}\n\n/**\n * Coerces a resolved placeholder value to a string. Primitives are stringified\n * the normal way; objects and arrays are JSON-encoded so downstream agents can\n * consume complex step outputs (e.g. `foreach(agent)` returns `{ text }[]`)\n * directly in a template. `null`/`undefined` render as empty. If JSON encoding\n * fails (circular references, BigInt, etc.), throws with a hint pointing at\n * the offending placeholder.\n */\nfunction stringifyTemplateValue(v: unknown, template: string, idx: number, rawExpr: string): string {\n  if (v === null || v === undefined) return '';\n  if (typeof v === 'object') {\n    try {\n      return JSON.stringify(v);\n    } catch (err) {\n      throw new Error(\n        `${describeBadPlaceholder(template, idx, rawExpr)} resolved to a value that could not be JSON-stringified ` +\n          `(${(err as Error).message}). Drill into a primitive path (e.g. \\${${rawExpr}.someField}) or reshape the value in a preceding step.`,\n      );\n    }\n  }\n  return String(v);\n}\n\n/**\n * Resolves `${<scope>.<path>}` placeholders against the implicit namespaces\n * available in a step's execute context. See the `.map()` overload signature\n * for the full list of accepted scopes (`inputData`, `initData`, `state`,\n * `requestContext`, `stepResults.<stepId>`).\n */\nexport function resolveTemplate(template: string, ctx: any): string {\n  let idx = 0;\n  return template.replace(TEMPLATE_PLACEHOLDER, (_match, rawExpr: string) => {\n    idx++;","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/core/src/workflows/mapping-template.ts#L105-L141","documentation":"When a template placeholder resolves to an object (or array), it is serialized with JSON.stringify for interpolation. If the resolved value cannot be stringified (e.g. circular references or BigInt values), stringifyTemplateValue throws advising the user to drill into a primitive field or reshape the value upstream.","triggerScenarios":"A placeholder like \"${stepResults.myStep}\" resolves to an object containing a circular reference or BigInt (e.g. a BigInt field, class instances with cyclic refs), and the value is interpolated into a string template.","commonSituations":"Steps returning database rows/ORM entities with cycles; BigInt IDs from blockchain or DB drivers; returning whole response objects instead of primitive fields into string templates.","solutions":["Reference a concrete primitive path instead of the whole object: \"${stepResults.myStep.id}\".","Convert BigInt/circular fields to strings/numbers in the producing step before mapping.","If the whole object is needed, JSON-serialize it safely in the prior step (e.g. a JSON.stringify with replacer) and reference that string."],"exampleFix":"// before\nprompt.push('${stepResults.dbRow}'); // row contains BigInt\n// after\nprompt.push('${stepResults.dbRow.id}');","handlingStrategy":"validation","validationCode":"function isJsonSerializable(v: unknown): boolean {\n  try { JSON.stringify(v); return true; } catch { return false; }\n}\n// before mapping: if (!isJsonSerializable(stepOutput)) normalize it upstream","typeGuard":"function isPlainSerializable(v: unknown): boolean {\n  if (typeof v === 'bigint') return false;\n  if (typeof v !== 'object' || v === null) return true;\n  try { JSON.stringify(v); return true; } catch { return false; }\n}","tryCatchPattern":"try {\n  run.workflow.mapVariable({ value: '${stepResults.myStep}' });\n} catch (err) {\n  if (err instanceof Error && err.message.includes('could not be JSON-stringified')) {\n    console.error('Value contains BigInt/circular refs; drill into a primitive path');\n  } else throw err;\n}","preventionTips":["Interpolate primitive fields, not whole objects, into string templates.","Convert BigInt values to string/number at step boundaries (e.g. DB/ORM rows).","Avoid returning class instances with circular references from steps."],"tags":["workflow","template","serialization","json"],"backgroundTag":"json-serialization-failed","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}