mastra-ai/mastra · error · Error

Tool '${entry.toolId}' not found for workflow step '${entry.

Error message

Tool '${entry.toolId}' not found for workflow step '${entry.id}'. Pass the tool instance directly.

What it means

executeTool resolves a tool referenced by string id via mastra.getTool at run time. If no tool instance was passed directly on the step entry and the id is not found on the Mastra instance, the step throws this error. Unlike agents, there is no registry fallback suggested — the message says to pass the tool instance directly.

Source

Thrown at packages/core/src/workflows/default.ts:1219

    const agent = entry.agent ?? this.mastra?.getAgentById(entry.agentId);
    if (!agent) {
      throw new Error(
        `Agent '${entry.agentId}' not found for workflow step '${entry.id}'. Register the agent on the Mastra instance or pass the agent instance directly.`,
      );
    }
    return this.executeStep({ ...rest, step: { ...createStepFromAgent(agent as any, entry.options), id: entry.id } });
  }

  /**
   * Executes a declarative `tool` step: resolves the tool (live ref, else
   * `mastra.getTool(toolId)`), builds its runnable step, and runs it through the
   * shared step runner.
   */
  async executeTool(params: ExecuteToolParams): Promise<StepExecutionResult> {
    const { entry, ...rest } = params;
    const tool = entry.tool ?? this.mastra?.getTool(entry.toolId);
    if (!tool) {
      throw new Error(
        `Tool '${entry.toolId}' not found for workflow step '${entry.id}'. Pass the tool instance directly.`,
      );
    }
    return this.executeStep({ ...rest, step: { ...createStepFromTool(tool as any, entry.options), id: entry.id } });
  }

  /**
   * Executes a declarative `mapping` step: builds the mapping step from the
   * declarative config/fn and runs it through the shared step runner.
   */
  async executeMapping(params: ExecuteMappingParams): Promise<StepExecutionResult> {
    const { entry, ...rest } = params;
    return this.executeStep({ ...rest, step: createMappingStep(entry.id, entry.mapConfig) });
  }

  async executeParallel(params: ExecuteParallelParams): Promise<StepResult<any, any, any, any>> {
    return executeParallelHandler(this, params);
  }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Register the tool on the Mastra instance: new Mastra({ tools: { weatherTool } }).
  2. Pass the tool instance directly on the step entry (`entry.tool`) so no id lookup is needed.
  3. Correct the toolId string in the definition/stored graph.

Example fix

// before
{ type: 'tool', id: 'step1', toolId: 'weatherTool' } // tool not registered
// after
new Mastra({ tools: { weatherTool } }) // or: { type: 'tool', id: 'step1', tool: weatherTool }
Defensive patterns

Strategy: validation

Validate before calling

const tool = entry.tool ?? mastra.getTool?.(entry.toolId);
if (!tool) {
  throw new Error(`Tool '${entry.toolId}' is not registered on the Mastra instance before running the workflow`);
}

Type guard

function toolIsResolvable(entry: { tool?: unknown; toolId?: string }, mastra: Mastra): boolean {
  return Boolean(entry.tool) || Boolean(entry.toolId && mastra.getTool(entry.toolId));
}

Try / catch

try {
  await workflow.start({ inputData });
} catch (e) {
  if (e instanceof Error && e.message.includes("not found for workflow step")) {
    // register the missing tool or pass the tool instance, then retry
  }
  throw e;
}

Prevention

When it happens

Trigger: A dynamic/stored workflow graph entry `{ type: 'tool', toolId: 'weatherTool' }` executes while the tool is not registered on the Mastra instance (`new Mastra({ tools: { weatherTool } })` missing or misspelled), or the workflow has no Mastra instance reference.

Common situations: Stored workflow definitions referencing tools that were deleted or renamed; tools defined locally in a file but never attached to Mastra; importing a workflow definition from another project where the tool doesn't exist; typo in toolId.

Related errors


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