moeru-ai/airi · error · Error

Unable to reload missing extension session: ${sessionId}

Error message

Unable to reload missing extension session: ${sessionId}

What it means

Thrown by ExtensionHost.reload() when no session exists for the given sessionId. Reload preserves the prior session's manifest, cwd, and runtime intent, so it requires a live session to read that state from; without one it cannot deterministically re-bootstrap.

Source

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

    return await this.dependencies.waitFor(key, timeoutMs)
  }

  async stop(sessionId: string): Promise<ExtensionSession | undefined> {
    const extensionSession = this.extensionSessionService.get(sessionId)
    if (!extensionSession) {
      return undefined
    }

    await this.cleanupExtensionSession(extensionSession)
    return extensionSession
  }

  async reload(sessionId: string, options: ExtensionStartOptions = {}): Promise<ExtensionSession> {
    // Reload preserves manifest/runtime intent, then performs stop + fresh start.
    // This intentionally creates a new session identity for deterministic re-bootstrap.
    const previousExtension = this.extensionSessionService.get(sessionId)
    if (!previousExtension) {
      throw new Error(`Unable to reload missing extension session: ${sessionId}`)
    }

    const manifest = previousExtension.manifest
    await this.cleanupExtensionSession(previousExtension)
    return this.start(manifest, {
      ...options,
      cwd: options.cwd ?? previousExtension.cwd,
      runtime: options.runtime ?? previousExtension.runtime,
    })
  }
}

View on GitHub (pinned to 27111382b4)

Solutions

  1. Confirm the session is still live via host.getSession(sessionId) before calling reload().
  2. If the session was stopped, call host.start(manifest) with the original manifest instead of reload().
  3. Avoid calling reload() concurrently with stop(); serialize teardown and restart.

Example fix

// before
await host.stop(session.id)
await host.reload(session.id) // throws: session already removed

// after
const existing = host.getSession(session.id)
if (existing) {
  await host.reload(session.id)
} else {
  await host.start(manifest)
}
Defensive patterns

Strategy: validation

Validate before calling

const session = host.getSession(sessionId)
if (!session) {
  throw new Error(`Session '${sessionId}' is not active. Use host.start(manifest) instead of reload.`)
}
await host.reload(sessionId)

Type guard

function canReload(host: ExtensionHost, sessionId: string): boolean {
  return host.getSession(sessionId) !== undefined
}

Try / catch

try {
  await host.reload(sessionId)
} catch (error) {
  if (error instanceof Error && /Unable to reload missing extension session/.test(error.message)) {
    // session gone; fall back to a fresh start with the original manifest
    await host.start(manifest)
  } else {
    throw error
  }
}

Prevention

When it happens

Trigger: Calling host.reload(sessionId) after the session was already stopped (host.stop removed it), was never started, or when passing a stale/typo sessionId.

Common situations: Calling reload on a session that was torn down by a previous stop() or cleanup. Holding a sessionId across a restart boundary. Using reload where start() on the manifest would be correct because the prior session is gone.

Related errors


AI-assisted analysis of moeru-ai/airi@27111382b4 (2026-08-12). Data as JSON: /api/errors/1ebf540e380cdd91. Report an issue: GitHub.