{"record":{"id":"5603a0ec03c0b606","repo":"moeru-ai/airi","slug":"extension-manifest-id-requires-airi-manifest-engines-airi","errorCode":null,"errorMessage":"Extension \\`${manifest.id}\\` requires AIRI \\`${manifest.engines.airi}\\`, but the running version is \\`${this.airiVersion}\\`.","messagePattern":"Extension \\\\`(.+?)\\\\` requires AIRI \\\\`(.+?)\\\\`, but the running version is \\\\`(.+?)\\\\`\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugin-sdk/src/plugin-host/core.ts","lineNumber":247,"sourceCode":"      throw new Error(`AIRI version must be a valid semantic version: ${options.airiVersion}`)\n    }\n    this.airiVersion = options.airiVersion\n    this.permissionResolver = options.permissionResolver\n    this.resources.setValue(protocolListProvidersEventName, [] as Array<{ name: string }>)\n    this.markCapabilityReady(protocolListProvidersEventName, { source: 'plugin-host' })\n    this.installContext = this.createInstallContext()\n\n    for (const contribution of options.contributions ?? []) {\n      this.installContribution(contribution)\n    }\n  }\n\n  private assertManifestCompatibility(manifest: ExtensionManifestV2, runtime: PluginRuntime) {\n    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 = {","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/moeru-ai/airi/blob/438a067dde47aa0bdb46c2323d1fe293dc805218/packages/plugin-sdk/src/plugin-host/core.ts#L229-L265","documentation":"When this.airiVersion is set, assertManifestCompatibility runs semver.satisfies(hostVersion, manifest.engines.airi, { includePrerelease: true }). If the running AIRI version does not satisfy the manifest's engines.airi range, the extension is refused. This protects extensions from being loaded by incompatible host versions.","triggerScenarios":"startExtension/start with a manifest whose engines.airi range excludes the current host version — e.g. host is 0.9.0 and manifest requires \"^1.0.0\".","commonSituations":"Upgrading or downgrading the AIRI host without updating extensions; an extension pinned to an old range; using a dev/nightly build against a manifest with an exact version pin; forgetting to bump engines.airi after a breaking release.","solutions":["Update manifest.engines.airi to a range that includes the running host version, then reinstall the extension.","Upgrade the AIRI host to a version within the manifest's required range.","Install a different extension release compatible with the current host.","If the version is a prerelease, ensure the range is expressed correctly — includePrerelease is already enabled, so the range itself must include the version."],"exampleFix":"// before\n\"engines\": { \"runtimes\": [\"electron\"], \"airi\": \"^0.9.0\" }  // host is 1.2.0\n// after\n\"engines\": { \"runtimes\": [\"electron\"], \"airi\": \">=0.9.0\" }","handlingStrategy":"validation","validationCode":"import semver from 'semver'\nconst compatible = semver.satisfies(hostVersion, manifest.engines.airi, { includePrerelease: true })\nif (!compatible) console.warn(`skip ${manifest.id}: requires airi ${manifest.engines.airi}`)","typeGuard":null,"tryCatchPattern":"try {\n  await host.start(extension)\n} catch (e) {\n  if (/requires AIRI/.test(e.message)) promptHostUpgrade(e.message)\n  else throw e\n}","preventionTips":["Use ranges (>= or ^) instead of exact pins in engines.airi unless strictly necessary.","Bump engines.airi as part of the release checklist when breaking changes ship.","Prefer installing extension versions built for your host version."],"tags":["plugin-host","semver","version-mismatch","manifest"],"backgroundTag":"incompatible-source-type","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"}