moeru-ai/airi · error · Error

Failed to resolve extension module. The entrypoint must expo

Error message

Failed to resolve extension module. The entrypoint must export defineExtension(...).

What it means

Thrown by coerceExtensionFromModule() when the imported entrypoint module is neither itself a valid Extension (object with string `id` and function `setup`) nor has a `default` export that is. The loader expects a defineExtension(...) result either as the namespace or as the default export.

Source

Thrown at packages/plugin-sdk/src/plugin-host/runtimes/node/loaders/fs.ts:28

    && 'id' in value
    && typeof (value as { id?: unknown }).id === 'string'
    && 'setup' in value
    && typeof (value as { setup?: unknown }).setup === 'function'
}

function coerceExtensionFromModule(moduleValue: unknown): Extension {
  if (isExtensionDefinition(moduleValue)) {
    return moduleValue
  }

  if (typeof moduleValue === 'object' && moduleValue !== null) {
    const defaultExport = (moduleValue as { default?: unknown }).default
    if (isExtensionDefinition(defaultExport)) {
      return defaultExport
    }
  }

  throw new Error('Failed to resolve extension module. The entrypoint must export defineExtension(...).')
}

/**
 * Loads extension entrypoints from the local filesystem for the current runtime.
 *
 * Use when:
 * - The host needs to resolve a manifest entrypoint path
 * - The host needs to import a `defineExtension(...)` export
 *
 * Expects:
 * - Entry points are valid importable module paths for the active runtime
 *
 * Returns:
 * - Filesystem-backed helpers for resolving and loading extension entrypoints
 */
export class FileSystemLoader {
  /**
   * Resolve a manifest entrypoint for the requested runtime.

View on GitHub (pinned to 27111382b4)

Solutions

  1. Ensure the entrypoint's default export is the result of defineExtension({ id, setup }): `export default defineExtension({ id, setup })`.
  2. Confirm the entrypoint file resolved by resolveEntrypointFor is the intended extension file, not a barrel/utility module.
  3. Verify the entrypoint exports an object with a string `id` and a function `setup` (the isExtensionDefinition contract).

Example fix

// before — extension.ts
import { defineExtension } from '@proj-airi/plugin-sdk'
const ext = defineExtension({ id: 'my-ext', setup(ctx) { /* ... */ } }) // not exported

// after
export default defineExtension({ id: 'my-ext', setup(ctx) { /* ... */ } })
Defensive patterns

Strategy: type-guard

Validate before calling

const mod = await import(entrypoint)
const candidate = mod.default ?? mod
if (typeof candidate !== 'object' || candidate === null
    || typeof candidate.id !== 'string'
    || typeof candidate.setup !== 'function') {
  throw new Error(`Entrypoint '${entrypoint}' does not export a defineExtension(...) result`)
}

Type guard

function isExtensionDefinition(value: unknown): value is Extension {
  return typeof value === 'object'
    && value !== null
    && 'id' in value
    && typeof (value as { id?: unknown }).id === 'string'
    && 'setup' in value
    && typeof (value as { setup?: unknown }).setup === 'function'
}

Try / catch

try {
  const extension = await loader.loadExtensionFor(manifest, options)
} catch (error) {
  if (error instanceof Error && /Failed to resolve extension module/.test(error.message)) {
    // entrypoint does not export defineExtension(...); fix the entrypoint exports
  } else {
    throw error
  }
}

Prevention

When it happens

Trigger: The entrypoint file resolved by resolveEntrypointFor imports successfully but does not export defineExtension(...) output correctly — e.g. it exports a plain object, a function, or forgets `export default`. Also triggered if defineExtension is called but the result is not exported (just invoked for side effects).

Common situations: Entrypoint file is empty or a stub. Author wrote `defineExtension({ id, setup })` without `export default`. The file exports the extension under a named export (e.g. `export const ext = ...`) instead of default. The resolved path points at the wrong file (e.g. an index that re-exports utilities).

Related errors


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