moeru-ai/airi · error · Error

Extension entrypoint id \

Error message

Extension entrypoint id \`${extension.id}\` must match manifest id \`${options.manifest.id}\`.

What it means

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).

Solutions

  1. Make the extension entrypoint's exported id identical to the manifest id.
  2. Rebuild the extension so the entrypoint reflects the current manifest id.
  3. Check you are loading the correct entrypoint file for this manifest (entrypoints[runtime] or entrypoints.default).
  4. Clear bundler caches if a rename did not propagate to the built output.

Example fix

// before (entrypoint)
defineExtension({ id: 'old-name', setup() {} })
// after
defineExtension({ id: 'new-name', setup() {} })
Defensive patterns

Strategy: validation

Validate before calling

if (extension.id !== manifest.id) {
  console.error(`entrypoint id ${extension.id} != manifest id ${manifest.id}`)
}

Try / catch

try {
  await host.startExtension(extension, { manifest })
} catch (e) {
  if (e.message.includes('must match manifest id')) reportStaleBuild(manifest.id)
  else throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of moeru-ai/airi@438a067dde (2026-09-17). Data as JSON: /api/errors/0760b114dc1d88c8. Report an issue: GitHub.

Appendix: source

Thrown at packages/plugin-sdk/src/plugin-host/core.ts:261

    if (!manifest.engines.runtimes.includes(runtime)) {
      throw new Error(`Extension \`${manifest.id}\` does not support runtime \`${runtime}\`.`)
    }
    if (this.airiVersion && !semver.satisfies(this.airiVersion, manifest.engines.airi, { includePrerelease: true })) {
      throw new Error(
        `Extension \`${manifest.id}\` requires AIRI \`${manifest.engines.airi}\`, but the running version is \`${this.airiVersion}\`.`,
      )
    }
  }

  async startExtension(
    extension: Extension,
    options: { manifest: ExtensionManifestV2, cwd?: string, runtime?: PluginRuntime },
  ) {
    const runtime = options.runtime ?? this.runtime
    this.assertManifestCompatibility(options.manifest, runtime)

    if (extension.id !== options.manifest.id) {
      throw new Error(`Extension entrypoint id \`${extension.id}\` must match manifest id \`${options.manifest.id}\`.`)
    }

    const sessionIdentity = this.extensionSessionService.nextSessionIdentity()
    const extensionIdentity = {
      id: extension.id,
      version: options.manifest.version,
      sessionId: sessionIdentity.sessionId,
    }
    const persistedGrant = this.persistedPermissionGrants.get(extension.id)
    const resolvedGrant = await this.permissionResolver?.({
      identity: extensionIdentity,
      manifest: options.manifest,
      requested: options.manifest.permissions,
      persisted: persistedGrant,
    }) ?? options.manifest.permissions
    const permissionSnapshot = this.permissions.initialize(sessionIdentity.sessionId, options.manifest.permissions, {
      grant: resolvedGrant,
      persisted: this.permissionResolver ? undefined : persistedGrant,

View on GitHub (pinned to 438a067dde)