mastra-ai/mastra · error · Error

${describeBadPlaceholder(template, idx, rawExpr)} resolved t

Error message

${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.

What it means

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.

Source

Thrown at packages/core/src/workflows/mapping-template.ts:123

  }
  return ids;
}

/**
 * Coerces a resolved placeholder value to a string. Primitives are stringified
 * the normal way; objects and arrays are JSON-encoded so downstream agents can
 * consume complex step outputs (e.g. `foreach(agent)` returns `{ text }[]`)
 * directly in a template. `null`/`undefined` render as empty. If JSON encoding
 * fails (circular references, BigInt, etc.), throws with a hint pointing at
 * the offending placeholder.
 */
function stringifyTemplateValue(v: unknown, template: string, idx: number, rawExpr: string): string {
  if (v === null || v === undefined) return '';
  if (typeof v === 'object') {
    try {
      return JSON.stringify(v);
    } catch (err) {
      throw new Error(
        `${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.`,
      );
    }
  }
  return String(v);
}

/**
 * Resolves `${<scope>.<path>}` placeholders against the implicit namespaces
 * available in a step's execute context. See the `.map()` overload signature
 * for the full list of accepted scopes (`inputData`, `initData`, `state`,
 * `requestContext`, `stepResults.<stepId>`).
 */
export function resolveTemplate(template: string, ctx: any): string {
  let idx = 0;
  return template.replace(TEMPLATE_PLACEHOLDER, (_match, rawExpr: string) => {
    idx++;

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Reference a concrete primitive path instead of the whole object: "${stepResults.myStep.id}".
  2. Convert BigInt/circular fields to strings/numbers in the producing step before mapping.
  3. 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.

Example fix

// before
prompt.push('${stepResults.dbRow}'); // row contains BigInt
// after
prompt.push('${stepResults.dbRow.id}');
Defensive patterns

Strategy: validation

Validate before calling

function isJsonSerializable(v: unknown): boolean {
  try { JSON.stringify(v); return true; } catch { return false; }
}
// before mapping: if (!isJsonSerializable(stepOutput)) normalize it upstream

Type guard

function isPlainSerializable(v: unknown): boolean {
  if (typeof v === 'bigint') return false;
  if (typeof v !== 'object' || v === null) return true;
  try { JSON.stringify(v); return true; } catch { return false; }
}

Try / catch

try {
  run.workflow.mapVariable({ value: '${stepResults.myStep}' });
} catch (err) {
  if (err instanceof Error && err.message.includes('could not be JSON-stringified')) {
    console.error('Value contains BigInt/circular refs; drill into a primitive path');
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/37781d6d9b5ea3da. Report an issue: GitHub.