mastra-ai/mastra · error · Error

Plugin instructions must be a string

Error message

Plugin instructions must be a string

What it means

resolvePluginInstructions accepts a plugin's `instructions` either as a static string or a function returning a string (possibly async). After resolving, if the resulting value is not a string, the loader throws 'Plugin instructions must be a string'. This catches plugins whose instructions function returns undefined, null, a number, a Promise that resolved to a non-string, or an object.

Source

Thrown at mastracode/sdk/src/plugins/loader.ts:293

    throw new Error('Plugin processor lanes must be arrays');
  }
  for (const processor of [...input, ...output]) {
    if (!processor || typeof processor !== 'object' || typeof processor.id !== 'string') {
      throw new Error('Plugin processors must be objects with an id');
    }
  }
  return { input, output };
}

async function resolvePluginInstructions(
  plugin: MastraCodePlugin,
  context: MastraCodePluginContext,
): Promise<string | undefined> {
  if (plugin.instructions === undefined) return undefined;
  const instructions =
    typeof plugin.instructions === 'function' ? await plugin.instructions(context) : plugin.instructions;
  if (typeof instructions !== 'string') {
    throw new Error('Plugin instructions must be a string');
  }
  const trimmed = instructions.trim();
  return trimmed.length > 0 ? trimmed : undefined;
}

function normalizePluginToolEntries(entries: MastraCodePluginToolEntries): {
  tools: MastraCodePluginTools;
  renderConfigs: Record<string, MastraCodeToolRenderConfig>;
} {
  const tools: MastraCodePluginTools = {};
  const renderConfigs: Record<string, MastraCodeToolRenderConfig> = {};
  for (const [name, entry] of Object.entries(entries)) {
    if (!isToolEntryObject(entry)) {
      throw new Error(`Plugin tool "${name}" must be an object with a tool property`);
    }
    tools[name] = entry.tool;
    if (entry.render) renderConfigs[name] = entry.render;
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Make the plugin's instructions a plain string, or ensure the instructions function always returns a string (call .trim() yourself and return '' if empty is intended).
  2. If the function can return undefined on some path, return an empty string instead so the loader treats it as 'no instructions'.
  3. If returning structured data, flatten it to a string (e.g. JSON.stringify or joining lines) before returning.
  4. Log/inspect the resolved value (typeof instructions) at the plugin boundary to find the offending return type.

Example fix

// before
instructions: async (ctx) => ({ text: `Mode: ${ctx.mode}` })
// after
instructions: async (ctx) => `Mode: ${ctx.mode}`
Defensive patterns

Strategy: type-guard

Validate before calling

const resolved = typeof plugin.instructions === 'function' ? await plugin.instructions(ctx) : plugin.instructions;
if (resolved !== undefined && typeof resolved !== 'string') {
  throw new TypeError(`Plugin ${plugin.name}: instructions must resolve to a string, got ${typeof resolved}`);
}

Type guard

function isPluginInstructions(v: unknown): v is string | ((ctx: MastraCodePluginContext) => string | Promise<string>) {
  return typeof v === 'string' || typeof v === 'function';
}

Try / catch

try {
  const instructions = await manager.instructions();
} catch (err) {
  if (err instanceof Error && err.message === 'Plugin instructions must be a string') {
    console.error('Plugin returned non-string instructions; check the instructions() return type');
  } else throw err;
}

Prevention

When it happens

Trigger: Calling instructions()/resolvePluginInstructions on a plugin where (a) `instructions` is set to a non-string non-function value, or (b) `instructions` is a function whose return/awaited result is not a string, e.g. `instructions: () => undefined`, `instructions: async () => ({ text: '...' })`, or `instructions: () => someNumber`.

Common situations: A plugin author returns an object like { body: '...' } from the instructions callback assuming structured instructions are supported; a function conditionally returns undefined on some branch; a refactor changed the return type from string to Promise<SummaryObject>; a config value typed as any leaks in as instructions.

Related errors


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