mastra-ai/mastra · error · MastraError

AGENT_FS_ROUTING_INSTRUCTIONS_INVALID

AGENT_FS_ROUTING_INSTRUCTIONS_INVALID

Error message

Agent "${name}": agents/${name}/instructions.ts must default-export a string, a system message, an array of either, or a function returning one, but got ${received}.

What it means

When an Agent is defined via filesystem routing, packages/core reads agents/<name>/instructions.ts and expects its default export to be a string, a system message object, an array of those, or a function returning one of those. assertValidInstructionsModule (via resolveInstructions) inspects the runtime value of the default export and throws this error when none of the supported shapes match. It is a USER-category configuration error: the instructions file exists but its export shape is not usable.

Source

Thrown at packages/core/src/agent/fs-routing/index.ts:487

 * no default export at all never reaches here; the bundler fails first, naming
 * the same file.)
 */
function assertValidInstructionsModule(
  name: string,
  instructions: unknown,
): asserts instructions is DynamicArgument<AgentInstructions> {
  const isUsable =
    typeof instructions === 'function' ||
    (Array.isArray(instructions)
      ? instructions.length > 0 && instructions.every(isUsableSystemMessage)
      : isUsableSystemMessage(instructions));

  if (isUsable) {
    return;
  }

  const received = describeInstructionsExport(instructions);
  throw new MastraError({
    id: 'AGENT_FS_ROUTING_INSTRUCTIONS_INVALID',
    domain: ErrorDomain.AGENT,
    category: ErrorCategory.USER,
    details: { agentName: name, received },
    text: `Agent "${name}": agents/${name}/instructions.ts must default-export a string, a system message, an array of either, or a function returning one, but got ${received}.`,
  });
}

/**
 * One entry of an `AgentInstructions` value: a bare string, or a system message
 * whose `content` is a string. Anything else reaches the model as an empty
 * string, so the entries have to be checked rather than just the container —
 * `[123]` is exactly as mute as `123`.
 */
function isUsableSystemMessage(value: unknown): boolean {
  return (
    typeof value === 'string' ||
    (typeof value === 'object' && value !== null && typeof (value as { content?: unknown }).content === 'string')

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Make instructions.ts default-export a plain string: `export default 'You are a helpful assistant.'`
  2. If you need rich behavior, default-export a function that returns a string, system message, or array of them (sync or async), and verify the return value with the same shape rules.
  3. Add the missing `default` keyword if you exported a named constant (`export default instructions` instead of `export const instructions`).
  4. Log/inspect the default export at runtime (`import mod from './instructions.ts'; console.log(describeInstructionsExport(mod))`) to see what shape the resolver actually received.

Example fix

// before (agents/support/instructions.ts)
export const instructions = { instructions: 'You are support.' };

// after
export default 'You are support.';
Defensive patterns

Strategy: validation

Validate before calling

import mod from './agents/support/instructions.ts';
function isUsableInstructions(v: unknown): boolean {
  const isSystemMessage = (x: unknown): x is { role: string; content: string } =>
    !!x && typeof x === 'object' && 'role' in x && 'content' in x;
  if (typeof v === 'string' || isSystemMessage(v)) return true;
  if (Array.isArray(v) && v.every(x => typeof x === 'string' || isSystemMessage(x))) return true;
  if (typeof v === 'function') return true; // must return one of the above when called
  return false;
}
if (!isUsableInstructions(mod)) throw new Error('instructions.ts default export shape invalid');

Type guard

function isSystemMessage(v: unknown): v is { role: string; content: string } {
  return typeof v === 'object' && v !== null && 'role' in v && 'content' in v && typeof (v as any).content === 'string';
}

Try / catch

try {
  agent = await resolveAgentFromFs('support');
} catch (e) {
  if (e instanceof MastraError && e.id === 'AGENT_FS_ROUTING_INSTRUCTIONS_INVALID') {
    console.error('Fix agents/support/instructions.ts:', e.detail?.received);
  } else throw e;
}

Prevention

When it happens

Trigger: Creating agents/<name>/instructions.ts with `export default { instructions: '...' }` (nested object), `export default undefined`, a class instance, a Promise, or a function returning an unsupported value; forgetting the `default` keyword entirely so the module's default export is undefined; exporting a named constant instead of default-exporting it.

Common situations: Migrating from an older format where instructions lived in config.ts to the dedicated instructions.ts file; copy-pasting instructions into a wrapper object; TypeScript compile of the file failing so the import yields undefined; authors exporting `async function` that resolves to undefined instead of returning a string/system message.

Related errors


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