mastra-ai/mastra · error · Error
Plugin "${pluginId}" is not installed in ${scope} scope
Error message
Plugin "${pluginId}" is not installed in ${scope} scope What it means
setEnabled toggles a plugin's enabled flag in the registry file for a given scope (e.g. project/user). Before writing, it loads that scope's registry and requires a record for pluginId; if none exists it throws 'Plugin "<id>" is not installed in <scope> scope'. The check is scope-specific — a plugin installed at user scope is not visible in the project registry.
Source
Thrown at mastracode/sdk/src/plugins/manager.ts:522
url: string,
scope: PluginScope,
options: Pick<InstallPluginOptions, 'entry' | 'ref' | 'onOutput' | 'signal'> = {},
): Promise<string> {
const id = await installGithubPlugin(url, scope, { ...this.options, ...options });
// Installing over an existing checkout replaces it at the same path, so the
// cached head would make a genuinely different commit stamp as unchanged and
// leave the previous signal providers running.
this.githubCheckoutHeads.clear();
await this.reload();
return id;
}
async setEnabled(pluginId: string, scope: PluginScope, enabled: boolean): Promise<void> {
const paths = getPluginScopePaths(scope, this.options);
const registry = loadPluginRegistry(paths.registryPath);
const record = registry.plugins[pluginId];
if (!record) {
throw new Error(`Plugin "${pluginId}" is not installed in ${scope} scope`);
}
savePluginRegistry(paths.registryPath, setPluginRecord(registry, pluginId, { ...record, enabled }));
await this.reload();
}
async setConfigValue(
pluginId: string,
scope: PluginScope,
key: string,
value: MastraCodePluginConfigValue,
): Promise<void> {
const paths = getPluginScopePaths(scope, this.options);
const registry = loadPluginRegistry(paths.registryPath);
const record = registry.plugins[pluginId];
if (!record) {
throw new Error(`Plugin "${pluginId}" is not installed in ${scope} scope`);
}
const config = { ...(record.config ?? {}) };View on GitHub (pinned to 75dd419e61)
Solutions
- Verify the exact pluginId via the plugin list/registry for that scope before calling setEnabled.
- Pass the correct scope — check which registry file (project vs user path from getPluginScopePaths) actually contains the plugin.
- Install the plugin in the target scope first, then call setEnabled.
- Fix typos/case mismatches in the plugin id string.
Example fix
// before
await manager.setEnabled('my-plugn', PluginScope.PROJECT, true);
// after
const installed = manager.list().some(p => p.id === 'my-plugin' && p.scope === 'project');
if (installed) await manager.setEnabled('my-plugin', PluginScope.PROJECT, true); Defensive patterns
Strategy: validation
Validate before calling
const installed = await manager.list(); // or read registry.plugins for the scope
if (!installed.some(p => p.id === pluginId && p.scope === scope)) {
throw new Error(`Refusing: plugin "${pluginId}" not installed in ${scope} scope`);
} Try / catch
try {
await manager.setEnabled(pluginId, scope, enabled);
} catch (err) {
if (err instanceof Error && err.message.includes('is not installed in')) {
const match = err.message.match(/Plugin "(.+)" is not installed in (.+) scope/);
console.error(`Check id '${match?.[1]}' and scope '${match?.[2]}'; available: ${await listPluginIds()}`);
} else throw err;
} Prevention
- Resolve plugin ids from the registry/list output rather than hardcoding strings.
- Always pair scope with how the plugin was installed (user vs project registry paths).
- Install-then-configure: run install before any enable/config calls in scripts and CI.
When it happens
Trigger: Calling manager.setEnabled(pluginId, scope, enabled) where pluginId was never installed in that scope: typo in the plugin id, wrong scope argument (e.g. PluginScope.PROJECT when it is installed at USER scope), enabling a plugin before running install, or the registry file was deleted/reset.
Common situations: Scripting enable/disable with an id copied from a different machine's registry; team repo where the plugin is registered in .mastracode user config but the code passes project scope; stale registry after branch switch; hardcoding plugin ids that were renamed in a newer version.
Related errors
- tool_result must be preceded by a tool_call
- mastra-wrapper plugin did not return code, there is likely a
- Could not create the session. Reload the page and try again.
- Plugin id mismatch: registry has "${record.id}" but module e
- Plugin path for "${record.id}" must be inside the ${record.s
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/a093c5ec62445c0c.
Report an issue: GitHub.