{"record":{"id":"b4c50266ea76a0e0","repo":"coleam00/Archon","slug":"pi-extension-load-failed-message-check-the-ex","errorCode":null,"errorMessage":"Pi extension load failed: ${message}. Check the extensions in ~/.pi/agent/extensions/ (and the repo's .pi/), or set `assistants.pi.enableExtensions: false` to run without them.","messagePattern":"Pi extension load failed: (.+?)\\. Check the extensions in ~/\\.pi/agent/extensions/ \\(and the repo's \\.pi/\\), or set `assistants\\.pi\\.enableExtensions: false` to run without them\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/providers/src/community/pi/resource-loader.ts","lineNumber":233,"sourceCode":"      // would silently never apply.\n      try {\n        await loader.reload();\n        // Snapshot NOW, before any session's bindCore() drains the queue into\n        // its own ModelRegistry and clears it. Defensive copy: bindCore()\n        // reassigns the array, so the copy stays stable, but a copy also\n        // guards against future in-place mutation upstream.\n        const providerRegistrations: ExtensionProviderRegistration[] = [\n          ...loader.getExtensions().runtime.pendingProviderRegistrations,\n        ];\n        return { loader, providerRegistrations };\n      } catch (error) {\n        // Extensions execute arbitrary JS from ~/.pi/agent/extensions/ (and the\n        // repo's .pi/); a broken one fails here. Rethrow with an actionable\n        // pointer, preserving the original error as `cause`, so the operator\n        // isn't left with a bare Pi SDK message. The failed promise is evicted\n        // below, so the next call retries cleanly.\n        const message = error instanceof Error ? error.message : String(error);\n        throw new Error(\n          `Pi extension load failed: ${message}. Check the extensions in ~/.pi/agent/extensions/ ` +\n            \"(and the repo's .pi/), or set `assistants.pi.enableExtensions: false` to run without them.\",\n          { cause: error }\n        );\n      }\n    })();\n    reloadedExtensionLoaderCache.set(key, pending);\n    // Evict on failure so a transient reload error doesn't poison the cache.\n    pending.catch(() => reloadedExtensionLoaderCache.delete(key));\n  }\n  return pending;\n}\n\n/**\n * Test-only: clear the process-level loader cache so each test starts empty.\n * The cache is module-level and would otherwise leak loaders (and their mocked\n * reload/construct call counts) across tests in the same file.\n */","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/coleam00/Archon/blob/0773b9745896ef0612e709c80845a0f7db315b19/packages/providers/src/community/pi/resource-loader.ts#L215-L251","documentation":"getOrCreateReloadedExtensionLoader loads Pi extensions (arbitrary JS) from ~/.pi/agent/extensions/ and the repo's .pi/. If an extension throws during load, the failed promise is evicted for clean retry and the error is rethrown with an actionable pointer, preserving the original as `cause`.","triggerScenarios":"sendQuery/listPiModels triggering extension loading when any extension file in ~/.pi/agent/extensions/ or .pi/ throws on import, has a syntax error, a missing dependency, or an incompatibility with the current Pi SDK version.","commonSituations":"A broken/half-edited extension script, an extension requiring an npm package not installed, an extension written against an older Pi SDK after an upgrade, or a repo-local .pi/ extension left over from another project.","solutions":["Read the `cause` in the message/logs to find which extension failed, then fix or remove it from ~/.pi/agent/extensions/ (and repo .pi/)","Temporarily set assistants.pi.enableExtensions: false in .archon/config.yaml to run without extensions","Update or reinstall the broken extension (e.g. `pi install npm:pi-provider-kiro`)","Check the extension's dependencies are installed and compatible with the current Pi SDK version"],"exampleFix":"// before: broken ~/.pi/agent/extensions/myext.js\nimport missingPkg from 'not-installed';\n// after: either remove the file or install its dependency\n$ npm install -g not-installed   # or delete ~/.pi/agent/extensions/myext.js","handlingStrategy":"try-catch","validationCode":"import { existsSync, readdirSync } from 'node:fs';\nconst extDirs = [`${process.env.HOME}/.pi/agent/extensions`, '.pi'].filter(existsSync);\nfor (const dir of extDirs) {\n  for (const f of readdirSync(dir)) {\n    if (f.endsWith('.js')) {\n      try { await import(`${dir}/${f}`); } catch (e) { console.error(`Extension ${f} fails to load: ${e.message}`); }\n    }\n  }\n}","typeGuard":"function isExtensionLoadError(e: unknown): boolean {\n  return e instanceof Error && e.message.startsWith('Pi extension load failed');\n}","tryCatchPattern":"try {\n  await sendQuery(q);\n} catch (err) {\n  if (isExtensionLoadError(err)) {\n    log.error({ cause: err.cause }, 'pi extension failed; fix/remove it or set enableExtensions: false');\n  }\n  throw err;\n}","preventionTips":["Test extension scripts with `node --check` / a smoke import after editing them","Keep extensions' npm dependencies installed and updated for the Pi SDK version","Remove stale repo-local .pi/ extensions you don't need","Set assistants.pi.enableExtensions: false in environments where extensions aren't required"],"tags":["extensions","pi","module-load"],"backgroundTag":"extension-load-failed","analyzedSha":"0773b9745896ef0612e709c80845a0f7db315b19","analyzedAt":"2026-09-01T02:28:07.064Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}