{"record":{"id":"bc497f78b2b26765","repo":"can1357/oh-my-pi","slug":"trusted-extension-must-be-an-existing-module-file","errorCode":null,"errorMessage":"Trusted extension must be an existing module file: ${trustedPath}","messagePattern":"Trusted extension must be an existing module file: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/main.ts","lineNumber":395,"sourceCode":"\tauthStorage: AuthStorage;\n\tmodelRegistry: ModelRegistry;\n\tparsedArgs: Pick<Args, \"apiKey\" | \"trustedExtensions\" | \"tools\">;\n\trawArgs: string[];\n\tcreateSession: (options: CreateAgentSessionOptions) => Promise<CreateAgentSessionResult>;\n}\n\nasync function loadTrustedSessionExtensions(\n\toptions: Pick<CreateAgentSessionOptions, \"additionalExtensionPaths\">,\n\tcwd: string,\n\teventBus: EventBus,\n) {\n\tconst paths = options.additionalExtensionPaths ?? [];\n\tfor (const trustedPath of paths) {\n\t\tlet stat: fsSync.Stats;\n\t\ttry {\n\t\t\tstat = fsSync.statSync(trustedPath);\n\t\t} catch {\n\t\t\tthrow new Error(`Trusted extension must be an existing module file: ${trustedPath}`);\n\t\t}\n\t\tif (!stat.isFile()) {\n\t\t\tthrow new Error(`Trusted extension must be a module file, not a directory: ${trustedPath}`);\n\t\t}\n\t}\n\treturn loadExtensions(paths, cwd, eventBus);\n}\n\n/**\n * Build the per-`session/new` factory used by ACP mode.\n *\n * MCP servers in ACP sessions are owned exclusively by the ACP client, which\n * supplies them through `session/new.mcpServers` and re-applies them via\n * {@link AcpAgent#configureMcpServers}. We therefore force `enableMCP: false`\n * on every session created here so {@link createAgentSession} skips the on-disk\n * `.mcp.json` discovery path — otherwise host MCP tools land in the session's\n * tool registry and shadow the client-supplied servers (issue #1234).\n */","sourceCodeStart":377,"sourceCodeEnd":413,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/main.ts#L377-L413","documentation":"loadTrustedSessionExtensions validates each explicitly trusted extension path before loading. If statSync fails — the path does not exist or is inaccessible — it throws this error, because a trusted extension is loaded with full privileges and must point at a real module file.","triggerScenarios":"Starting omp with additionalExtensionPaths (trusted extensions) containing a path that does not exist, has a typo, or is not readable — raised in loadTrustedSessionExtensions during startup extension resolution.","commonSituations":"Config drift after moving/deleting an extension file; absolute paths baked into config on another machine; wrong casing or extension (.js vs .ts) in the configured path; symlinks pointing at removed targets.","solutions":["Correct the configured path in your omp config / CLI flag so it points at the existing extension module file.","Delete or comment out the stale trusted-extension entry if the extension is no longer needed.","Verify the path with `ls -l <path>` and that the target is a regular file (directories raise the sibling 'not a directory' error).","Reinstall or rebuild the extension if it was removed by a clean/rebuild."],"exampleFix":"// before\nomp --extension /home/me/extensions/my-ext.ts  // file deleted\n// after\nbun build extensions/my-ext.ts --outfile ~/.omp/extensions/my-ext.js\nomp --extension ~/.omp/extensions/my-ext.js","handlingStrategy":"validation","validationCode":"import * as fsSync from \"node:fs\";\nfunction trustedExtensionPathsOk(paths: string[]) {\n  return paths.filter(p => { try { return fsSync.statSync(p).isFile(); } catch { return false; } });\n}","typeGuard":"function isModuleFile(p: string): p is string {\n  try { return fsSync.statSync(p).isFile(); } catch { return false; }\n}","tryCatchPattern":"try {\n  await startSession({ additionalExtensionPaths });\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"Trusted extension must be\")) {\n    const missing = err.message.split(\": \")[1];\n    console.error(`Fix or remove trusted extension path: ${missing}`);\n    return startSession({ additionalExtensionPaths: paths.filter(p => p !== missing) });\n  } throw err;\n}","preventionTips":["Validate extension paths at config-load time and warn instead of failing at startup.","Use paths relative to a stable config dir, and re-resolve symlinks after rebuilds.","Keep extension files out of clean/build wipe targets, or reinstall them in a postinstall hook."],"tags":["extensions","filesystem","config","startup"],"backgroundTag":"file-not-found","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}