{"record":{"id":"8a862cde71048354","repo":"mastra-ai/mastra","slug":"plugin-module-must-export-a-plugin-object-as-defau","errorCode":null,"errorMessage":"Plugin module must export a plugin object as default or named \"plugin\" export","messagePattern":"Plugin module must export a plugin object as default or named \"plugin\" export","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/plugins/loader.ts","lineNumber":171,"sourceCode":"\nasync function importPluginModule(entryPath: string): Promise<MastraCodePlugin> {\n  if (path.extname(entryPath) !== '.ts') {\n    throw new Error(\n      `Unsupported plugin entry extension \"${path.extname(entryPath)}\". V1 plugins must use .ts entries.`,\n    );\n  }\n\n  const url = pathToFileURL(entryPath);\n  const stat = fs.statSync(entryPath, { bigint: true });\n  url.searchParams.set('mtimeNs', stat.mtimeNs.toString());\n  url.searchParams.set('size', stat.size.toString());\n  const mod = (await import(url.href)) as { default?: unknown; plugin?: unknown };\n  return validatePluginExport(mod.default ?? mod.plugin);\n}\n\nfunction validatePluginExport(value: unknown): MastraCodePlugin {\n  if (!value || typeof value !== 'object') {\n    throw new Error('Plugin module must export a plugin object as default or named \"plugin\" export');\n  }\n\n  const plugin = value as MastraCodePlugin;\n  if (typeof plugin.id !== 'string' || plugin.id.trim().length === 0) {\n    throw new Error('Plugin id must be a non-empty string');\n  }\n\n  if (plugin.tools !== undefined && typeof plugin.tools !== 'object' && typeof plugin.tools !== 'function') {\n    throw new Error('Plugin tools must be an object or function');\n  }\n\n  if (\n    plugin.processors !== undefined &&\n    typeof plugin.processors !== 'object' &&\n    typeof plugin.processors !== 'function'\n  ) {\n    throw new Error('Plugin processors must be an array, object, or function');\n  }","sourceCodeStart":153,"sourceCodeEnd":189,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/plugins/loader.ts#L153-L189","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before (entry.ts)\nexport const tools = { ... }; // no default or 'plugin' export\n// after\nexport const plugin = {\n  id: 'widgets',\n  name: 'Widgets',\n  tools: () => ({ ... }),\n};\nexport default plugin;","handlingStrategy":"type-guard","validationCode":"function isPluginExport(mod: unknown): mod is { default: { id: string } | undefined; plugin?: { id: string } } {\n  const m = mod as { default?: unknown; plugin?: unknown };\n  const candidate = m.default ?? m.plugin;\n  return typeof candidate === 'object' && candidate !== null && typeof (candidate as { id?: unknown }).id === 'string';\n}\nconst mod = await import(entryUrl);\nif (!isPluginExport(mod)) throw new Error('Entry must default-export (or name \"plugin\") an object with a string id');","typeGuard":"function isMastraCodePlugin(value: unknown): value is { id: string } {\n  return (\n    typeof value === 'object' &&\n    value !== null &&\n    typeof (value as { id?: unknown }).id === 'string' &&\n    (value as { id: string }).id.trim().length > 0\n  );\n}","tryCatchPattern":"const loaded = await loadPluginRecord(record, options);\nif (loaded.status === 'load failed' && loaded.error?.includes('must export a plugin object')) {\n  console.error(`${record.entry} needs: export default { id: '...', ... } or export const plugin = { id: '...', ... }`);\n}","preventionTips":["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."],"tags":["plugin-loading","module-exports","typescript","validation"],"backgroundTag":"missing-plugin-default-export","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}