mastra-ai/mastra · error

Tool must have input and output schemas defined

Error message

Tool must have input and output schemas defined

What it means

createStepFromTool requires the tool params to carry both inputSchema and outputSchema; if either is missing it throws. Schemas are needed to type and validate data flowing into and out of the tool-as-step.

Source

Thrown at packages/core/src/workflows/step-factories.ts:98

    __agentOptions: agentOrToolOptions,
  } as Step<TStepId, unknown, any, TStepOutput, unknown, unknown, DefaultEngineType>;
}

export function createStepFromTool<TStepInput, TSuspend, TResume, TStepOutput>(
  params: ToolStep<TStepInput, TSuspend, TResume, TStepOutput, any>,
  toolOpts?: {
    retries?: number;
    scorers?: DynamicArgument<MastraScorers>;
    metadata?: StepMetadata;
    /**
     * Overrides the FGA actor for this tool call. Wins over a propagating run
     * actor; pass `undefined` explicitly to drop back to user-actor resolution.
     */
    actor?: ActorSignal;
  },
): Step<string, any, TStepInput, TStepOutput, TResume, TSuspend, DefaultEngineType> {
  if (!params.inputSchema || !params.outputSchema) {
    throw new Error('Tool must have input and output schemas defined');
  }

  return {
    id: params.id,
    description: params.description,
    inputSchema: params.inputSchema,
    outputSchema: params.outputSchema,
    resumeSchema: params.resumeSchema,
    suspendSchema: params.suspendSchema,
    retries: toolOpts?.retries,
    scorers: toolOpts?.scorers,
    metadata: toolOpts?.metadata,
    // The run logic lives in `runToolEntry` (shared with the engines'
    // declarative-entry dispatch); this closure just binds the live tool.
    execute: async ctx =>
      runToolEntry({ type: 'tool', id: params.id, toolId: params.id, tool: params, options: toolOpts }, ctx),
    component: 'TOOL',
    // Preserve the declarative inputs so the workflow builder can emit a

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Define both inputSchema and outputSchema on the tool before passing it to createStepFromTool.
  2. Check the tool factory/constructor used to build the tool and ensure it emits both schemas.
  3. If a schema is genuinely unused, supply an explicit trivial schema (e.g. z.object({})).
  4. Type the tool with the library's Tool type so missing schemas are a compile-time error.

Example fix

// before
createStepFromTool({ id: 'myTool', execute: async (i) => i });
// after
import { z } from 'zod';
createStepFromTool({
  id: 'myTool',
  inputSchema: z.object({ q: z.string() }),
  outputSchema: z.object({ answer: z.string() }),
  execute: async ({ q }) => ({ answer: q.toUpperCase() }),
});
Defensive patterns

Strategy: validation

Validate before calling

function hasSchemas(tool: { inputSchema?: unknown; outputSchema?: unknown }) {
  if (!tool.inputSchema || !tool.outputSchema) throw new Error('Tool must have input and output schemas defined');
}

Type guard

function isSchemaComplete<T extends { inputSchema?: unknown; outputSchema?: unknown }>(t: T): t is T & { inputSchema: NonNullable<T['inputSchema']>; outputSchema: NonNullable<T['outputSchema']> } {
  return t.inputSchema != null && t.outputSchema != null;
}

Try / catch

try {
  const step = createStepFromTool(tool);
} catch (e) {
  if ((e as Error).message === 'Tool must have input and output schemas defined') {
    console.error(`Tool '${tool.id}' is missing schemas`);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling createStepFromTool (or createStep/tool helpers that route to it) with a tool object lacking inputSchema or outputSchema — e.g. a hand-built tool object, a tool imported from code that defines only one schema, or a dynamically constructed tool where schemas were added conditionally.

Common situations: Tools built programmatically where one schema was forgotten; migrating tools from an API that made schemas optional; tools deserialized from storage without their schema metadata.

Related errors


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