mastra-ai/mastra · error · Error

${describeBadPlaceholder(template, idx, rawExpr)} requires a

Error message

${describeBadPlaceholder(template, idx, rawExpr)} requires a request-context key — use ${requestContext.<key>}.

What it means

requestContext-scoped placeholders must name a key: ${requestContext.<key>}. If the placeholder is exactly "${requestContext}" with no key, validateTemplate throws because there is nothing to look up in the request context.

Source

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

      throw new Error(
        `${describeBadPlaceholder(template, idx, rawExpr)} has empty or whitespace-padded contents. ` +
          `Use \${<scope>.<path>} with no surrounding whitespace.`,
      );
    }
    const { scope, rest } = parseTemplatePlaceholder(rawExpr);
    if (scope === 'stepResults') {
      const innerDot = rest.indexOf('.');
      const stepId = innerDot === -1 ? rest : rest.slice(0, innerDot);
      if (!stepId) {
        throw new Error(
          `${describeBadPlaceholder(template, idx, rawExpr)} must be of the form \${stepResults.<stepId>} or \${stepResults.<stepId>.<path>}.`,
        );
      }
      continue;
    }
    if (scope === 'requestContext') {
      if (!rest) {
        throw new Error(
          `${describeBadPlaceholder(template, idx, rawExpr)} requires a request-context key — use \${requestContext.<key>}.`,
        );
      }
      continue;
    }
    if ((TEMPLATE_NAMESPACES as readonly string[]).includes(scope)) continue;
    throw new Error(
      `${describeBadPlaceholder(template, idx, rawExpr)} references unknown namespace "${scope}". ` +
        `Use one of: ${TEMPLATE_NAMESPACES.join(', ')}.`,
    );
  }
}

/**
 * Collects the step ids referenced by `${stepResults.<stepId>}` /
 * `${stepResults.<stepId>.<path>}` placeholders in a template. Assumes the
 * template already passed {@link validateTemplate}; malformed placeholders are
 * skipped. Used by validation to scope-check template references against the

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Specify the key: "${requestContext.userId}".
  2. If multiple values are needed, reference each key in separate placeholders or build it in a preceding step.
  3. Add build-time validateTemplate() coverage for templates.

Example fix

// before
mapVariable({ value: '${requestContext}' });
// after
mapVariable({ value: '${requestContext.tenantId}' });
Defensive patterns

Strategy: validation

Validate before calling

const tpl = '${requestContext.tenantId}';
for (const m of tpl.matchAll(/\$\{([^}]*)\}/g)) {
  const [scope, key] = m[1].split('.');
  if (scope === 'requestContext' && !key) throw new Error(`${m[0]} needs a requestContext key`);
}

Try / catch

try {
  validateTemplate(tpl);
} catch (err) {
  if (err instanceof Error && err.message.includes('request-context key')) {
    console.error(`Template '${tpl}' must name a requestContext key`);
  } else throw err;
}

Prevention

When it happens

Trigger: Writing "${requestContext}" alone in a mapping template passed to mapVariable/map/analyzeMapConfig.

Common situations: Assuming the whole request context can be injected as one value; deleting the key after the dot during edits.

Related errors


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