{"record":{"id":"f26c91fc1563c721","repo":"moeru-ai/airi","slug":"extension-entrypoint-is-required-for-runtime-ru","errorCode":null,"errorMessage":"Extension entrypoint is required for runtime `${runtime}`. Define one of `entrypoints.<runtime>`, `entrypoints.default`, or `entrypoints.electron` in the extension manifest.","messagePattern":"Extension entrypoint is required for runtime `(.+?)`\\. Define one of `entrypoints\\.<runtime>`, `entrypoints\\.default`, or `entrypoints\\.electron` in the extension manifest\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugin-sdk/src/plugin-host/runtimes/node/loaders/fs.ts","lineNumber":62,"sourceCode":"export class FileSystemLoader {\n  /**\n   * Resolve a manifest entrypoint for the requested runtime.\n   *\n   * Resolution order:\n   * 1) `entrypoints.<runtime>`\n   * 2) `entrypoints.default`\n   * 3) `entrypoints.electron` (legacy fallback for current local extension manifests)\n   */\n  resolveEntrypointFor(manifest: ExtensionManifestV1, options?: ExtensionLoadOptions) {\n    const runtime = options?.runtime ?? 'electron'\n    const root = options?.cwd ?? cwd()\n    const entrypoint\n      = manifest.entrypoints[runtime]\n        ?? manifest.entrypoints.default\n        ?? manifest.entrypoints.electron\n\n    if (!entrypoint) {\n      throw new Error(''\n        + `Extension entrypoint is required for runtime \\`${runtime}\\`. `\n        + 'Define one of `entrypoints.<runtime>`, `entrypoints.default`, '\n        + 'or `entrypoints.electron` in the extension manifest.',\n      )\n    }\n\n    return isAbsolute(entrypoint) ? entrypoint : join(root, entrypoint)\n  }\n\n  async loadExtensionFor(manifest: ExtensionManifestV1, options?: ExtensionLoadOptions) {\n    const entrypoint = this.resolveEntrypointFor(manifest, options)\n    const extensionModule = await import(entrypoint)\n    return coerceExtensionFromModule(extensionModule)\n  }\n}\n","sourceCodeStart":44,"sourceCodeEnd":78,"githubUrl":"https://github.com/moeru-ai/airi/blob/677329427f32468c74b17f3ec47eeca4e05bec65/packages/plugin-sdk/src/plugin-host/runtimes/node/loaders/fs.ts#L44-L78","documentation":"Thrown by FileSystemLoader.resolveEntrypointFor when the manifest's entrypoints map has no entry for the requested runtime, no default, and no electron fallback. Resolution order is entrypoints[runtime] ?? entrypoints.default ?? entrypoints.electron, where runtime defaults to 'electron' when ExtensionLoadOptions.runtime is omitted — so all three keys being absent is a manifest contract violation.","triggerScenarios":"Manifest with entrypoints: {} or a single entry under a different key (e.g. entrypoints.web) while loading with the default 'electron' runtime; loading under runtime: 'node' when only entrypoints.electron is defined; typo'd runtime key like 'Node'; manifest generated by scaffolding that skipped the entrypoints section.","commonSituations":"Writing manifests by hand for a new extension; running the same manifest under a new runtime without adding per-runtime entries; build tools that prune 'unused' manifest fields; migrating manifests where the runtime name changed casing.","solutions":["Add a runtime-agnostic entry to the manifest: \"entrypoints\": { \"default\": \"./dist/index.js\" }.","Or add the specific key for the runtime you load with: \"entrypoints\": { \"node\": \"./dist/index.node.js\" }.","Pass options.runtime explicitly to loadExtensionFor/host.start so it matches a key that exists in the manifest.","Validate manifests at scaffolding time (e.g. a check that entrypoints.default or the target runtime key is present)."],"exampleFix":"// before (manifest.json)\n{\n  \"id\": \"my-ext\",\n  \"entrypoints\": { \"web\": \"./dist/index.js\" }\n}\n// loadExtensionFor(manifest) -> runtime defaults to 'electron', no match -> throws\n\n// after\n{\n  \"id\": \"my-ext\",\n  \"entrypoints\": { \"default\": \"./dist/index.js\", \"web\": \"./dist/index.js\" }\n}","handlingStrategy":"validation","validationCode":"// Before loadExtensionFor / host.start:\nconst runtime = options?.runtime ?? 'electron'\nconst hasEntrypoint = Boolean(\n  manifest.entrypoints[runtime]\n    ?? manifest.entrypoints.default\n    ?? manifest.entrypoints.electron,\n)\nif (!hasEntrypoint) {\n  throw new Error(`Manifest ${manifest.id} lacks entrypoints for runtime '${runtime}'; add entrypoints.default`)\n}","typeGuard":"const hasRunnableEntrypoint = (m: ExtensionManifestV1, runtime: string): boolean =>\n  Boolean(m.entrypoints[runtime as keyof typeof m.entrypoints] ?? m.entrypoints.default ?? m.entrypoints.electron)","tryCatchPattern":null,"preventionTips":["Always include entrypoints.default in generated manifests as the safety net.","Validate manifests with a schema check at install/scaffold time, including the entrypoints keys.","Pass options.runtime explicitly so resolution does not silently fall back to 'electron'."],"tags":["plugin-sdk","manifest","entrypoints","loader"],"backgroundTag":"missing-manifest-field","analyzedSha":"677329427f32468c74b17f3ec47eeca4e05bec65","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}