mastra-ai/mastra · error · Error

${PLUGIN_MANIFEST_FILE} must contain a plugins array

Error message

${PLUGIN_MANIFEST_FILE} must contain a plugins array

What it means

After successful JSON parsing, loadPluginManifest() requires the root object to have a `plugins` array. If the top level is not an object or `plugins` is missing/not an array, it throws this error. This catches manifests with the wrong shape rather than failing later with confusing undefined errors.

Source

Thrown at mastracode/sdk/src/plugins/manifest.ts:30

export type PluginManifest = {
  plugins: PluginManifestEntry[];
};

export function loadPluginManifest(rootDir: string): PluginManifest | undefined {
  const manifestPath = path.join(rootDir, PLUGIN_MANIFEST_FILE);
  if (!fs.existsSync(manifestPath)) return undefined;

  let parsed: unknown;
  try {
    parsed = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
  } catch (error) {
    throw new Error(
      `Could not parse ${PLUGIN_MANIFEST_FILE}: ${error instanceof Error ? error.message : String(error)}`,
    );
  }

  if (!parsed || typeof parsed !== 'object' || !Array.isArray((parsed as { plugins?: unknown }).plugins)) {
    throw new Error(`${PLUGIN_MANIFEST_FILE} must contain a plugins array`);
  }

  return {
    plugins: (parsed as { plugins: unknown[] }).plugins.map((entry, index) => validateManifestEntry(entry, index)),
  };
}

export function savePluginManifest(rootDir: string, manifest: PluginManifest): void {
  fs.writeFileSync(path.join(rootDir, PLUGIN_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`);
}

export function upsertPluginManifestEntry(rootDir: string, entry: PluginManifestEntry): void {
  const manifest = loadPluginManifest(rootDir) ?? { plugins: [] };
  const validatedEntry = validateManifestEntry(entry, manifest.plugins.length);
  const existingIndex = manifest.plugins.findIndex(plugin => plugin.id === validatedEntry.id);
  if (existingIndex >= 0) {
    manifest.plugins[existingIndex] = validateManifestEntry(validatedEntry, existingIndex);
  } else {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Make the top level an object with a `plugins` array: `{ "plugins": [ ... ] }`.
  2. Check the key spelling is exactly `plugins`.
  3. Regenerate the file programmatically via savePluginManifest to guarantee the correct shape.
  4. Diff against a known-good `.mastracode-plugin.json` from a working project.

Example fix

// before
[{ "id": "a", "entry": "./a.ts" }]
// after
{ "plugins": [{ "id": "a", "entry": "./a.ts" }] }
Defensive patterns

Strategy: type-guard

Validate before calling

import fs from 'node:fs';
const parsed: unknown = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
if (!parsed || typeof parsed !== 'object' || !Array.isArray((parsed as { plugins?: unknown }).plugins)) {
  throw new Error('.mastracode-plugin.json must be an object with a plugins array');
}

Type guard

function isPluginManifest(value: unknown): value is { plugins: unknown[] } {
  return (
    !!value && typeof value === 'object' && Array.isArray((value as { plugins?: unknown }).plugins)
  );
}

Try / catch

try {
  const manifest = loadPluginManifest(rootDir);
} catch (error) {
  if (error instanceof Error && error.message.includes('must contain a plugins array')) {
    console.error('Manifest shape wrong — expected { "plugins": [...] }');
    return;
  }
  throw error;
}

Prevention

When it happens

Trigger: `.mastracode-plugin.json` exists in rootDir, parses as valid JSON, but is e.g. a top-level array, `null`, `{}`, or has `"plugins": {...}` or a misspelled key like `"plugin": [...]`.

Common situations: Authoring the manifest from scratch with the wrong schema; confusing this file with another plugin config format; a tool rewriting the file with a different top-level structure; typos in the `plugins` key.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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