{"record":{"id":"0760b114dc1d88c8","repo":"moeru-ai/airi","slug":"extension-entrypoint-id-extension-id-must-match-manifest-id","errorCode":null,"errorMessage":"Extension entrypoint id \\`${extension.id}\\` must match manifest id \\`${options.manifest.id}\\`.","messagePattern":"Extension entrypoint id \\\\`(.+?)\\\\` must match manifest id \\\\`(.+?)\\\\`\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugin-sdk/src/plugin-host/core.ts","lineNumber":261,"sourceCode":"    if (!manifest.engines.runtimes.includes(runtime)) {\n      throw new Error(`Extension \\`${manifest.id}\\` does not support runtime \\`${runtime}\\`.`)\n    }\n    if (this.airiVersion && !semver.satisfies(this.airiVersion, manifest.engines.airi, { includePrerelease: true })) {\n      throw new Error(\n        `Extension \\`${manifest.id}\\` requires AIRI \\`${manifest.engines.airi}\\`, but the running version is \\`${this.airiVersion}\\`.`,\n      )\n    }\n  }\n\n  async startExtension(\n    extension: Extension,\n    options: { manifest: ExtensionManifestV2, cwd?: string, runtime?: PluginRuntime },\n  ) {\n    const runtime = options.runtime ?? this.runtime\n    this.assertManifestCompatibility(options.manifest, runtime)\n\n    if (extension.id !== options.manifest.id) {\n      throw new Error(`Extension entrypoint id \\`${extension.id}\\` must match manifest id \\`${options.manifest.id}\\`.`)\n    }\n\n    const sessionIdentity = this.extensionSessionService.nextSessionIdentity()\n    const extensionIdentity = {\n      id: extension.id,\n      version: options.manifest.version,\n      sessionId: sessionIdentity.sessionId,\n    }\n    const persistedGrant = this.persistedPermissionGrants.get(extension.id)\n    const resolvedGrant = await this.permissionResolver?.({\n      identity: extensionIdentity,\n      manifest: options.manifest,\n      requested: options.manifest.permissions,\n      persisted: persistedGrant,\n    }) ?? options.manifest.permissions\n    const permissionSnapshot = this.permissions.initialize(sessionIdentity.sessionId, options.manifest.permissions, {\n      grant: resolvedGrant,\n      persisted: this.permissionResolver ? undefined : persistedGrant,","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/moeru-ai/airi/blob/438a067dde47aa0bdb46c2323d1fe293dc805218/packages/plugin-sdk/src/plugin-host/core.ts#L243-L279","documentation":"startExtension verifies that the id on the loaded extension entrypoint object equals the id declared in its ExtensionManifestV2. A mismatch means the entrypoint file and manifest disagree about which extension they represent, so the host aborts registration to avoid attribution bugs (contribution routing, session identity, permissions).","triggerScenarios":"Calling startExtension(extension, { manifest }) where extension.id !== options.manifest.id — typically after editing a manifest's id without rebuilding the entrypoint, or loading the wrong entrypoint file for a manifest.","commonSituations":"Renaming an extension in package.json/manifest but shipping a stale built entrypoint still exporting the old id; copy-pasting a manifest from another extension; bundler caching an old default export.","solutions":["Make the extension entrypoint's exported id identical to the manifest id.","Rebuild the extension so the entrypoint reflects the current manifest id.","Check you are loading the correct entrypoint file for this manifest (entrypoints[runtime] or entrypoints.default).","Clear bundler caches if a rename did not propagate to the built output."],"exampleFix":"// before (entrypoint)\ndefineExtension({ id: 'old-name', setup() {} })\n// after\ndefineExtension({ id: 'new-name', setup() {} })","handlingStrategy":"validation","validationCode":"if (extension.id !== manifest.id) {\n  console.error(`entrypoint id ${extension.id} != manifest id ${manifest.id}`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  await host.startExtension(extension, { manifest })\n} catch (e) {\n  if (e.message.includes('must match manifest id')) reportStaleBuild(manifest.id)\n  else throw e\n}","preventionTips":["Derive the entrypoint id from the manifest/package id at build time instead of hardcoding.","Always rebuild after renaming an extension.","Add a unit test asserting entrypoint.id === manifest.id."],"tags":["plugin-host","identity-mismatch","manifest","extensions"],"backgroundTag":"invalid-identifier-format","analyzedSha":"438a067dde47aa0bdb46c2323d1fe293dc805218","analyzedAt":"2026-09-17T01:14:42.644Z","contentChangedAt":"2026-09-17T01:14:42.644Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}