mastra-ai/mastra · error · Error

Plugin tool "${toolName}" is no longer available

Error message

Plugin tool "${toolName}" is no longer available

What it means

Live plugin tools are proxied: on each execute() the manager reloads changed local plugins and looks the tool up by name in the latest rawPluginTools map. If the tool no longer exists (or lost its execute) after a reload, the proxy throws 'Plugin tool "<name>" is no longer available' instead of silently calling a stale implementation.

Source

Thrown at mastracode/sdk/src/plugins/manager.ts:231

      }
    }

    for (const [name, tool] of Object.entries(nextTools)) {
      this.rawPluginTools[name] = tool;
      if (!this.pluginTools[name]) {
        this.pluginTools[name] = this.createLiveToolProxy(name);
      }
      this.syncLiveToolProxy(name, tool);
    }
  }

  private createLiveToolProxy(toolName: string) {
    return {
      execute: async (...args: any[]) => {
        await this.reloadChangedLocalPlugins();
        const latestTool = this.rawPluginTools[toolName];
        if (!latestTool?.execute) {
          throw new Error(`Plugin tool "${toolName}" is no longer available`);
        }
        return (latestTool.execute as (...args: any[]) => unknown)(...args);
      },
    } as LoadedPlugin['tools'][string];
  }

  private syncLiveToolProxy(toolName: string, tool: LoadedPlugin['tools'][string]): void {
    const proxy = this.pluginTools[toolName];
    if (!proxy) return;
    const mutableProxy = proxy as unknown as Record<string, unknown>;
    for (const key of Object.keys(mutableProxy)) {
      delete mutableProxy[key];
    }
    Object.assign(proxy, tool);
    proxy.execute = this.createLiveToolProxy(toolName).execute;
  }

  private async reloadChangedLocalPlugins(): Promise<void> {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Re-resolve the tool from the manager after plugin changes instead of caching the old reference.
  2. Verify the plugin is still installed and enabled and that it still exports the tool under the same name.
  3. Fix any plugin source errors that make reload drop the tool (check reload logs).
  4. Restart the session/manager so the tool registry is rebuilt if hot-reload state is inconsistent.

Example fix

// before
const tool = manager.getTool('search'); // cached
await tool.execute(args); // may throw after reload
// after
const fresh = manager.getTool('search');
if (!fresh) throw new Error('tool removed');
await fresh.execute(args);
Defensive patterns

Strategy: try-catch

Validate before calling

const tool = manager.getTool?.(toolName) ?? manager.rawPluginTools?.[toolName];
if (!tool || typeof tool.execute !== 'function') {
  throw new Error(`Tool "${toolName}" unavailable; refusing to invoke stale proxy`);
}

Type guard

function isLiveTool(t: unknown): t is { execute: (...args: any[]) => unknown } {
  return typeof t === 'object' && t !== null && typeof (t as any).execute === 'function';
}

Try / catch

try {
  await pluginTool.execute(args);
} catch (err) {
  if (err instanceof Error && /is no longer available/.test(err.message)) {
    // re-fetch the tool from the manager and retry once, or surface a 'plugin changed' error
    const fresh = manager.getPluginTools()[toolName];
    if (fresh) return fresh.execute(args);
    throw new Error(`Tool ${toolName} was removed by a plugin reload`);
  }
  throw err;
}

Prevention

When it happens

Trigger: Holding a reference to a plugin tool and invoking execute() after (a) the plugin providing the tool was uninstalled/disabled, (b) the plugin renamed or removed the tool, (c) reloadChangedLocalPlugins picked up edited plugin source that no longer exports that tool, or (d) a plugin failed to reload so its tools vanished from rawPluginTools.

Common situations: Hot-reload during development while editing plugin code; an agent/workflow captured the tool reference earlier and runs later after the plugin changed; the plugin file was deleted or moved; a syntax error in the plugin caused a reload that dropped its tools; tool name refactored without updating callers.

Related errors


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