mastra-ai/mastra · error · Error
Plugin entry must be a .ts file
Error message
Plugin entry must be a .ts file
What it means
detectEntry requires explicit plugin entry files to be TypeScript (`.ts`) since plugins are loaded from TS source. This throw fires when the explicit entry has a different extension (e.g. `.js`, `.mjs`, or no extension treated as a file).
Source
Thrown at mastracode/sdk/src/plugins/install.ts:163
return detectEntry(pluginDir);
} catch {
return undefined;
}
}
export function detectEntry(pluginDir: string, explicitEntry?: string): string {
const root = path.resolve(pluginDir);
if (explicitEntry) {
const entryPath = path.resolve(pluginDir, explicitEntry);
if (!isInsideDirectory(entryPath, root)) {
throw new Error('Plugin entry must be inside the plugin directory');
}
if (fs.existsSync(entryPath) && fs.statSync(entryPath).isDirectory()) {
const nestedEntry = detectEntry(entryPath);
return path.relative(root, path.join(entryPath, nestedEntry));
}
if (path.extname(entryPath) !== '.ts') {
throw new Error('Plugin entry must be a .ts file');
}
if (!fs.existsSync(entryPath) || !fs.statSync(entryPath).isFile()) {
throw new Error(`Plugin entry file does not exist: ${explicitEntry}`);
}
return path.relative(root, entryPath);
}
const manifestPlugin = getSingleManifestPlugin(pluginDir);
if (manifestPlugin) {
return detectEntry(pluginDir, manifestPlugin.entry);
}
for (const candidate of ENTRY_CANDIDATES) {
const entryPath = path.join(pluginDir, candidate);
if (fs.existsSync(entryPath) && fs.statSync(entryPath).isFile()) {
return candidate;
}
}View on GitHub (pinned to 75dd419e61)
Solutions
- Point the entry at the TypeScript source file, e.g. `entry: 'src/index.ts'`.
- Rename/convert the entry to TypeScript if the plugin is authored in JS.
- Reference the `.ts` source, not a compiled `dist/*.js` output.
Example fix
// before
{ entry: 'dist/index.js' }
// after
{ entry: 'src/index.ts' } Defensive patterns
Strategy: validation
Validate before calling
import path from 'node:path';
export function assertTsEntry(entry: string): void {
if (path.extname(entry) !== '.ts') {
throw new Error(`Plugin entry must be a .ts file, got: ${entry}`);
}
} Type guard
function isTsEntry(entry: string): boolean {
return entry.endsWith('.ts') && !entry.endsWith('.d.ts');
} Prevention
- Author plugin entries in TypeScript; treat dist/*.js output as non-installable.
- Standardize entries as src/index.ts across plugin repos.
- Check the extension before saving `entry` in config.
When it happens
Trigger: Calling entry/detectEntry with explicitEntry whose resolved path has path.extname !== '.ts' and is not a directory, e.g. `entry: 'index.js'` or `entry: 'main.mjs'`.
Common situations: Authors porting a JS plugin; pointing at a compiled `dist/index.js`; omitting the extension on a file that is not a `.ts` candidate.
Related errors
- Plugin at ${pluginRoot} must declare an exact pnpm version i
- Plugin entry must be inside the plugin directory
- Plugin entry file does not exist: ${explicitEntry}
- Could not find a plugin entry file. Tried: ${ENTRY_CANDIDATE
- Invalid model provided. Model must be a MastraLanguageModel
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/79796fd7aa8cfffc.
Report an issue: GitHub.