mastra-ai/mastra · error · Error

Dynamic workflow references tool "${entry.toolId}" which is

Error message

Dynamic workflow references tool "${entry.toolId}" which is not registered on this Mastra instance.

What it means

Rehydrating a 'tool' entry requires a tool registered under `entry.toolId` on the target Mastra instance; `mastra.getTool(entry.toolId)` returning undefined causes this throw. Stored dynamic workflows reference tools by id, so any tool id missing from the runtime registry makes reconstruction impossible.

Source

Thrown at packages/core/src/workflows/dynamic/rehydrate.ts:275

    case 'agent': {
      const agent = tryGetAgentById(mastra, entry.agentId);
      if (!agent) {
        throw new Error(
          `Dynamic workflow references agent "${entry.agentId}" which is not registered on this Mastra instance.`,
        );
      }
      return {
        type: 'agent',
        id: entry.id,
        agentId: entry.agentId,
        agent,
        options: rebuildAgentOptions(entry, schemaOpts),
      };
    }
    case 'tool': {
      const tool = mastra.getTool?.(entry.toolId);
      if (!tool) {
        throw new Error(
          `Dynamic workflow references tool "${entry.toolId}" which is not registered on this Mastra instance.`,
        );
      }
      return { type: 'tool', id: entry.id, toolId: entry.toolId, tool, options: rebuildToolOptions(entry) };
    }
    case 'step': {
      const { id } = entry.step;
      // Wrap the resolved agent/tool in a real Step (same adapters `createStep`
      // uses) so the entry honors the executeStep contract instead of casting a
      // raw Agent/Tool instance — those don't carry a step-shaped `execute`.
      const agent = tryGetAgentById(mastra, id);
      if (agent) {
        return { type: 'step', step: createStepFromAgent(agent) as unknown as Step };
      }
      const tool = tryGetToolById(mastra, id);
      if (tool) {
        return { type: 'step', step: createStepFromTool(tool as any) as unknown as Step };
      }

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Register the missing tool: `new Mastra({ tools: { '<toolId>': myTool } })` before rehydrating.
  2. Confirm the stored `toolId` matches the registered id exactly after any renames.
  3. Align tool registration across environments (shared registry module) so stored graphs resolve everywhere.
  4. Pre-validate: for each stored tool entry, assert `mastra.getTool(toolId)` is defined before rehydrating.

Example fix

// before
const mastra = new Mastra({}); // graph references 'searchTool'

// after
const mastra = new Mastra({ tools: { searchTool } });
Defensive patterns

Strategy: validation

Validate before calling

function assertToolsRegistered(stored, mastra) {
  for (const e of stored.entries) {
    if (e.type === 'tool' && !mastra.getTool?.(e.toolId)) {
      throw new Error(`Tool "${e.toolId}" must be registered before rehydration`);
    }
  }
}

Type guard

function toolIsRegistered(mastra: Mastra, toolId: string): boolean {
  return !!mastra.getTool?.(toolId);
}

Try / catch

try {
  const wf = rehydrateWorkflow(stored, mastra);
} catch (err) {
  const m = err instanceof Error && err.message.match(/references tool "([^"]+)" which is not registered/);
  if (m) throw new Error(`Register tool '${m[1]}' on this Mastra instance before rehydrating.`);
  throw err;
}

Prevention

When it happens

Trigger: rehydrateWorkflow encounters a stored tool entry whose `toolId` is not resolvable via `mastra.getTool` — the tool was never passed into `new Mastra({ tools: {...} })`, was removed/renamed, or the stored graph came from a different deployment with a different tool set.

Common situations: Environment-specific tool registration (tool only exists in dev); renaming tool ids; tool defined in a package not installed in the deploying service; forgetting to include tools in the Mastra constructor.

Related errors


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