can1357/oh-my-pi · error
Trusted extension must be a module file, not a directory: ${
Error message
Trusted extension must be a module file, not a directory: ${trustedPath} What it means
loadTrustedSessionExtensions validates every path passed via --trusted-extension before loading it. After confirming the path exists (a missing path raises the sibling 'must be an existing module file' error), it stats the path and throws if it is not a regular file — e.g. a directory was supplied. Extensions are ES modules loaded via import, so only module files are valid.
Source
Thrown at packages/coding-agent/src/main.ts:398
rawArgs: string[];
createSession: (options: CreateAgentSessionOptions) => Promise<CreateAgentSessionResult>;
}
async function loadTrustedSessionExtensions(
options: Pick<CreateAgentSessionOptions, "additionalExtensionPaths">,
cwd: string,
eventBus: EventBus,
) {
const paths = options.additionalExtensionPaths ?? [];
for (const trustedPath of paths) {
let stat: fsSync.Stats;
try {
stat = fsSync.statSync(trustedPath);
} catch {
throw new Error(`Trusted extension must be an existing module file: ${trustedPath}`);
}
if (!stat.isFile()) {
throw new Error(`Trusted extension must be a module file, not a directory: ${trustedPath}`);
}
}
return loadExtensions(paths, cwd, eventBus);
}
/**
* Build the per-`session/new` factory used by ACP mode.
*
* MCP servers in ACP sessions are owned exclusively by the ACP client, which
* supplies them through `session/new.mcpServers` and re-applies them via
* {@link AcpAgent#configureMcpServers}. We therefore force `enableMCP: false`
* on every session created here so {@link createAgentSession} skips the on-disk
* `.mcp.json` discovery path — otherwise host MCP tools land in the session's
* tool registry and shadow the client-supplied servers (issue #1234).
*/
export function createAcpSessionFactory(args: AcpSessionFactoryOptions): AcpSessionFactory {
return async (cwd, factoryOptions) => {
const nextSettings = await args.settings.cloneForCwd(cwd);View on GitHub (pinned to 9690622007)
Solutions
- Pass the extension's module entry file (e.g. ~/.omp/extensions/my-ext/index.ts), not its directory.
- Check the path with ls: if it lists a directory, append the entry file name (index.ts/index.js or whatever package exports).
- If you want a directory of extensions loaded, list each module file explicitly as separate --trusted-extension flags.
Example fix
// before omp --trusted-extension ~/.omp/extensions/my-ext // after omp --trusted-extension ~/.omp/extensions/my-ext/index.ts
Defensive patterns
Strategy: validation
Validate before calling
import * as fsSync from "node:fs";
const trustedPath = process.argv[/* ... */];
const stat = fsSync.statSync(trustedPath);
if (!stat.isFile()) throw new Error(`--trusted-extension must be a file: ${trustedPath}`); Prevention
- Always point --trusted-extension at the entry module file, never a folder.
- Use tab-completion carefully: append /index.ts when a directory is completed.
- Script launchers should stat the path and assert isFile() before exec.
When it happens
Trigger: Running omp with --trusted-extension pointing at a directory that exists (e.g. --trusted-extension ./extensions or ~/.omp/extensions), instead of a concrete .ts/.js module file.
Common situations: Users assume extensions can be given as a folder to auto-load all files inside; shell tab-completion fills in a directory; docs or dotfiles point at an extension package directory rather than its entry file.
Related errors
- invalid template, {}, contains directory separator
- invalid suffix {}, contains directory separator
- Trusted extension failed to load: ${trustedExtensions.errors
- Trusted extension failed to load: ${extensionsResult.errors.
- --list-details, --exec, and --exec-batch are not supported b
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/1e62c288faf44666.
Report an issue: GitHub.