mastra-ai/mastra · error · Error

Could not find a plugin entry file. Tried

Error message

Could not find a plugin entry file. Tried: ${ENTRY_CANDIDATES.join(', ')}

What it means

When no explicit entry is given, detectEntry probes a list of conventional entry candidates (ENTRY_CANDIDATES) inside the plugin directory. If none exists as a regular file, the SDK throws listing all tried candidates so the author knows what to create.

Solutions

  1. Create one of the conventional entry files listed in the error message (typically `index.ts` at the plugin root).
  2. Set an explicit `entry` option pointing at your actual file, e.g. `entry: 'src/plugin.ts'`.
  3. Verify you are pointing the installer at the plugin's source directory, not `dist/` or a parent folder.
  4. Add a valid manifest declaring the plugin/entry if the convention differs.

Example fix

// before: plugin dir contains only plugin.ts, no config
mastra plugin install ./my-plugin

// after: specify the entry
mastra plugin install ./my-plugin --entry src/plugin.ts
// or add index.ts at the plugin root
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs';
import path from 'node:path';
const CANDIDATES = ['index.ts', 'src/index.ts', 'plugin.ts', 'src/plugin.ts'];
export function hasEntryCandidate(pluginDir: string): boolean {
  return CANDIDATES.some(c => {
    const p = path.join(pluginDir, c);
    return fs.existsSync(p) && fs.statSync(p).isFile();
  });
}
// if false, pass an explicit `entry` option

Try / catch

try {
  await installPlugin(dir);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Could not find a plugin entry file')) {
    // fall back to explicit entry
    return installPlugin(dir, { entry: 'src/main.ts' });
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling entry/detectEntry(pluginDir) with no explicitEntry, no single manifest plugin, and none of the ENTRY_CANDIDATES paths existing as files in pluginDir.

Common situations: Plugin directories missing an index.ts/mastra equivalent; entry lives in `src/` while only `dist/` output exists; empty or mis-created plugin folder; entry file named unconventionally (e.g. `plugin.ts`) without configuring `entry`.

Related errors


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

Appendix: source

Thrown at mastracode/sdk/src/plugins/install.ts:183

    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;
    }
  }

  throw new Error(`Could not find a plugin entry file. Tried: ${ENTRY_CANDIDATES.join(', ')}`);
}

function isInsideDirectory(targetPath: string, root: string): boolean {
  return targetPath === root || targetPath.startsWith(root + path.sep);
}

async function runPluginInstallCommand(
  command: string,
  args: string[],
  execaOptions: typeof NON_INTERACTIVE_EXEC_OPTIONS & { cwd?: string },
  options: PluginInstallExecutionOptions,
): Promise<void> {
  const child = execa(command, args, {
    ...execaOptions,
    stdout: options.onOutput ? 'pipe' : 'ignore',
    stderr: options.onOutput ? 'pipe' : 'ignore',
    cancelSignal: options.signal,
  });

View on GitHub (pinned to 75dd419e61)