mastra-ai/mastra · error · Error
Plugin module must export a plugin object as default or name
Error message
Plugin module must export a plugin object as default or named "plugin" export
What it means
After dynamically importing the entry module, the SDK accepts the default export or a named 'plugin' export and validates it is a non-null object (and subsequently that plugin.id is a non-empty string). If neither export exists or the export is not an object, the module cannot be recognized as a plugin and this error is thrown.
Source
Thrown at mastracode/sdk/src/plugins/loader.ts:171
async function importPluginModule(entryPath: string): Promise<MastraCodePlugin> {
if (path.extname(entryPath) !== '.ts') {
throw new Error(
`Unsupported plugin entry extension "${path.extname(entryPath)}". V1 plugins must use .ts entries.`,
);
}
const url = pathToFileURL(entryPath);
const stat = fs.statSync(entryPath, { bigint: true });
url.searchParams.set('mtimeNs', stat.mtimeNs.toString());
url.searchParams.set('size', stat.size.toString());
const mod = (await import(url.href)) as { default?: unknown; plugin?: unknown };
return validatePluginExport(mod.default ?? mod.plugin);
}
function validatePluginExport(value: unknown): MastraCodePlugin {
if (!value || typeof value !== 'object') {
throw new Error('Plugin module must export a plugin object as default or named "plugin" export');
}
const plugin = value as MastraCodePlugin;
if (typeof plugin.id !== 'string' || plugin.id.trim().length === 0) {
throw new Error('Plugin id must be a non-empty string');
}
if (plugin.tools !== undefined && typeof plugin.tools !== 'object' && typeof plugin.tools !== 'function') {
throw new Error('Plugin tools must be an object or function');
}
if (
plugin.processors !== undefined &&
typeof plugin.processors !== 'object' &&
typeof plugin.processors !== 'function'
) {
throw new Error('Plugin processors must be an array, object, or function');
}View on GitHub (pinned to 75dd419e61)
Solutions
- Add 'export default { id: "...", ... }' (or 'export const plugin = { id: "...", ... }') to the entry file.
- Ensure the exported value is a plain object with at least a non-empty string id.
- Check for circular imports or bundler settings that strip/rename the default export, causing it to be undefined at runtime.
Example fix
// before (entry.ts)
export const tools = { ... }; // no default or 'plugin' export
// after
export const plugin = {
id: 'widgets',
name: 'Widgets',
tools: () => ({ ... }),
};
export default plugin; Defensive patterns
Strategy: type-guard
Validate before calling
function isPluginExport(mod: unknown): mod is { default: { id: string } | undefined; plugin?: { id: string } } {
const m = mod as { default?: unknown; plugin?: unknown };
const candidate = m.default ?? m.plugin;
return typeof candidate === 'object' && candidate !== null && typeof (candidate as { id?: unknown }).id === 'string';
}
const mod = await import(entryUrl);
if (!isPluginExport(mod)) throw new Error('Entry must default-export (or name "plugin") an object with a string id'); Type guard
function isMastraCodePlugin(value: unknown): value is { id: string } {
return (
typeof value === 'object' &&
value !== null &&
typeof (value as { id?: unknown }).id === 'string' &&
(value as { id: string }).id.trim().length > 0
);
} Try / catch
const loaded = await loadPluginRecord(record, options);
if (loaded.status === 'load failed' && loaded.error?.includes('must export a plugin object')) {
console.error(`${record.entry} needs: export default { id: '...', ... } or export const plugin = { id: '...', ... }`);
} Prevention
- Always export the plugin object as default or as a named 'plugin' export.
- Give every plugin a non-empty string id in the exported object.
- Smoke-test the entry with `await import(entryPath)` and check the export shape before installing.
- Avoid circular imports that can leave the default export undefined at module init.
When it happens
Trigger: Entry file exports nothing, exports only named helpers, default-exports a class or function instead of a plugin object, or exports the plugin under a name other than 'plugin' or default; module whose default is null/undefined (e.g. re-export mistakes like 'export { default } from ...' where the target has no default).
Common situations: Writing the plugin file as plain utility code with no plugin export; using 'export const config = ...' style from other frameworks; accidental tree-shaking or a circular import yielding undefined at module evaluation time.
Related errors
- Unsupported plugin entry extension "${path.extname(entryPath
- ${label} must be a string.
- Invalid MemoryRequestContext.thread.id: expected string, got
- Invalid input: expected StepParams, Agent, ToolStep, or Proc
- observationalMemory.experimental_subconscious must be a Subc
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/8a862cde71048354.
Report an issue: GitHub.