{"record":{"id":"71d7396bcfc7caf0","repo":"mastra-ai/mastra","slug":"plugin-manifest-file-plugin-at-index-index-m-71d739","errorCode":null,"errorMessage":"${PLUGIN_MANIFEST_FILE} plugin at index ${index} must include an id","messagePattern":"(.+?) plugin at index (.+?) must include an id","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mastracode/sdk/src/plugins/manifest.ts","lineNumber":74,"sourceCode":"  if (!manifest) return undefined;\n  if (manifest.plugins.length === 0) return undefined;\n  if (manifest.plugins.length > 1) {\n    throw new Error(\n      `${PLUGIN_MANIFEST_FILE} contains multiple plugins. Provide an entry path for one of: ${manifest.plugins\n        .map(plugin => `${plugin.id} (${plugin.entry})`)\n        .join(', ')}`,\n    );\n  }\n  return manifest.plugins[0];\n}\n\nfunction validateManifestEntry(entry: unknown, index: number): PluginManifestEntry {\n  if (!entry || typeof entry !== 'object') {\n    throw new Error(`${PLUGIN_MANIFEST_FILE} plugin at index ${index} must be an object`);\n  }\n  const candidate = entry as { id?: unknown; name?: unknown; entry?: unknown };\n  if (typeof candidate.id !== 'string' || candidate.id.length === 0) {\n    throw new Error(`${PLUGIN_MANIFEST_FILE} plugin at index ${index} must include an id`);\n  }\n  if (typeof candidate.entry !== 'string' || candidate.entry.length === 0) {\n    throw new Error(`${PLUGIN_MANIFEST_FILE} plugin ${candidate.id} must include an entry`);\n  }\n  if (candidate.name !== undefined && typeof candidate.name !== 'string') {\n    throw new Error(`${PLUGIN_MANIFEST_FILE} plugin ${candidate.id} name must be a string`);\n  }\n  return {\n    id: candidate.id,\n    entry: candidate.entry,\n    ...(candidate.name ? { name: candidate.name } : {}),\n  };\n}\n","sourceCodeStart":56,"sourceCodeEnd":88,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/sdk/src/plugins/manifest.ts#L56-L88","documentation":"This error is thrown by validateManifestEntry when loading or updating the plugin manifest (plugins.json). Every entry in the manifest must have a non-empty string `id` so the plugin can be uniquely identified; entries without one are rejected. It exists to fail fast on malformed manifests rather than producing plugins with undefined identity downstream.","triggerScenarios":"Calling loadPluginManifest on a manifest file whose array contains an entry that is an object but has no `id` property, an `id` that is null/number/boolean, or `id: \"\"`. Also triggered by upsertPluginManifestEntry or validatedEntry passing such an object.","commonSituations":"Hand-editing plugins.json and forgetting the id field; renaming a plugin by deleting the id while restructuring; programmatically generating manifest entries from directory names that resolve to empty strings; JSON with a typo like \"Id\" instead of \"id\".","solutions":["Open the plugin manifest file and add a unique, non-empty string `id` to the entry at the reported index.","Verify the key is exactly lowercase `id` (not `Id` or `name`) and its value is a string with at least one character.","If the manifest is generated programmatically, fix the generator so every entry includes an id before writing.","Re-run the command to confirm the manifest validates."],"exampleFix":"// before (plugins.json entry)\n{ \"entry\": \"./dist/index.js\", \"name\": \"my-plugin\" }\n// after\n{ \"id\": \"my-plugin\", \"entry\": \"./dist/index.js\", \"name\": \"my-plugin\" }","handlingStrategy":"validation","validationCode":"const manifest = JSON.parse(fs.readFileSync('plugins.json', 'utf8'));\nmanifest.forEach((entry, i) => {\n  if (typeof entry?.id !== 'string' || entry.id.length === 0) {\n    throw new Error(`plugin at index ${i} must include a non-empty string id before load`);\n  }\n});","typeGuard":"function hasPluginId(entry: unknown): entry is { id: string } {\n  return typeof entry === 'object' && entry !== null &&\n    typeof (entry as { id?: unknown }).id === 'string' &&\n    (entry as { id: string }).id.length > 0;\n}","tryCatchPattern":"try {\n  loadPluginManifest(dir);\n} catch (err) {\n  if (err instanceof Error && err.message.includes('must include an id')) {\n    console.error(`Malformed manifest: ${err.message}`);\n    process.exitCode = 1;\n  } else throw err;\n}","preventionTips":["Keep a JSON schema or zod schema for the manifest and validate it in CI.","Never hand-edit plugins.json without re-running the validation step.","Use consistent lowercase key names (id, entry, name) in generators/templates."],"tags":["plugin-manifest","validation","configuration"],"backgroundTag":"manifest-entry-missing-required-field","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}