moeru-ai/airi · error · Error

Extension \` \` requires AIRI \` \`, but the running…

Error message

Extension \`${manifest.id}\` requires AIRI \`${manifest.engines.airi}\`, but the running version is \`${this.airiVersion}\`.

What it means

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.

Solutions

  1. Update manifest.engines.airi to a range that includes the running host version, then reinstall the extension.
  2. Upgrade the AIRI host to a version within the manifest's required range.
  3. Install a different extension release compatible with the current host.
  4. If the version is a prerelease, ensure the range is expressed correctly — includePrerelease is already enabled, so the range itself must include the version.

Example fix

// before
"engines": { "runtimes": ["electron"], "airi": "^0.9.0" }  // host is 1.2.0
// after
"engines": { "runtimes": ["electron"], "airi": ">=0.9.0" }
Defensive patterns

Strategy: validation

Validate before calling

import semver from 'semver'
const compatible = semver.satisfies(hostVersion, manifest.engines.airi, { includePrerelease: true })
if (!compatible) console.warn(`skip ${manifest.id}: requires airi ${manifest.engines.airi}`)

Try / catch

try {
  await host.start(extension)
} catch (e) {
  if (/requires AIRI/.test(e.message)) promptHostUpgrade(e.message)
  else throw e
}

Prevention

When it happens

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

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

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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

Appendix: source

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

      throw new Error(`AIRI version must be a valid semantic version: ${options.airiVersion}`)
    }
    this.airiVersion = options.airiVersion
    this.permissionResolver = options.permissionResolver
    this.resources.setValue(protocolListProvidersEventName, [] as Array<{ name: string }>)
    this.markCapabilityReady(protocolListProvidersEventName, { source: 'plugin-host' })
    this.installContext = this.createInstallContext()

    for (const contribution of options.contributions ?? []) {
      this.installContribution(contribution)
    }
  }

  private assertManifestCompatibility(manifest: ExtensionManifestV2, runtime: PluginRuntime) {
    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 = {

View on GitHub (pinned to 438a067dde)