can1357/oh-my-pi · error · ToolError

launch program resolves to a directory: ${displayPath}. Pass

Error message

launch program resolves to a directory: ${displayPath}. Pass an executable file path or choose an adapter that supports package directories.

What it means

The debug tool refuses to launch when the `program` path passed to `action: "launch"` resolves to a directory and the selected DAP adapter does not accept directory programs (`adapter.acceptsDirectoryProgram` is false). validateLaunchProgram throws this after adapter selection, since most adapters expect an executable file entry point. The path is shown with a trailing slash to make the directory nature obvious.

Source

Thrown at packages/coding-agent/src/tools/debug.ts:548

async function classifyLaunchProgram(program: string): Promise<LaunchProgramKind> {
	try {
		return (await fs.stat(program)).isDirectory() ? "directory" : "file";
	} catch (error) {
		if (isEnoent(error)) return "missing";
		throw error;
	}
}

function validateLaunchProgram(
	program: string,
	cwd: string,
	programKind: LaunchProgramKind,
	adapter: DapResolvedAdapter,
): void {
	if (programKind !== "directory" || adapter.acceptsDirectoryProgram) return;
	const displayPath = formatPathRelativeToCwd(program, cwd, { trailingSlash: true });
	throw new ToolError(
		`launch program resolves to a directory: ${displayPath}. Pass an executable file path or choose an adapter that supports package directories.`,
	);
}

interface DebugRenderArgs extends Partial<DebugParams> {}

function getActiveSessionSnapshot(): DapSessionSummary {
	const snapshot = dapSessionManager.getActiveSession();
	if (!snapshot) {
		throw new ToolError("No active debug session. Launch or attach first.");
	}
	return snapshot;
}

function requireCapability(capability: keyof DapCapabilities, description: string): DapSessionSummary {
	const snapshot = getActiveSessionSnapshot();
	if (dapSessionManager.getCapabilities()?.[capability] !== true) {
		throw new ToolError(`Current adapter does not support ${description}`);

View on GitHub (pinned to 9690622007)

Solutions

  1. Pass the executable file path instead of the directory (e.g. the entry script or compiled binary).
  2. Select an adapter that supports package directories (one with acceptsDirectoryProgram) via the `adapter` parameter.
  3. If launching a package, append the module entry point, e.g. point program at `pkg/__main__.py` or build first and launch the binary.

Example fix

// before
{ "action": "launch", "program": "./my-python-package" }
// after
{ "action": "launch", "program": "./my-python-package/__main__.py" }
Defensive patterns

Strategy: validation

Validate before calling

import * as fs from "node:fs";
const st = fs.statSync(programPath);
if (st.isDirectory()) {
  // pick a directory-capable adapter or resolve to an entry file first
}
if (!st.isFile()) throw new Error("program must be an executable file");

Type guard

function isFilePath(p: string): boolean {
  try { return fs.statSync(p).isFile(); } catch { return false; }
}

Try / catch

try {
  await debugTool({ action: "launch", program: p });
} catch (e) {
  if (String(e).includes("resolves to a directory")) {
    await debugTool({ action: "launch", program: path.join(p, "__main__.py") });
  }
}

Prevention

When it happens

Trigger: Calling the debug tool with action=launch and program set to a directory path (e.g. a package folder like `./myproject` or `~/src/app/`) when the chosen or auto-selected adapter requires a file program.

Common situations: Passing a Python package directory instead of `__main__.py` or the entry script; passing a project root to debugpy; passing a Go module directory instead of the built binary or main package; misconfigured launch configs that point at folders.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/d516edc9761fdf21. Report an issue: GitHub.