can1357/oh-my-pi · error · Error

git-subdir path "${source.path}" does not exist in cloned re

Error message

git-subdir path "${source.path}" does not exist in cloned repository

What it means

Thrown by verifyDirExists (via resolveRelativeSource/resolveObjectSource) after a marketplace plugin source of type git-subdir has been cloned: the configured `source.path` subdirectory does not exist inside the cloned repository, or exists but is a file rather than a directory. The resolver validates the target immediately after cloning and cleans up the temp clone before failing, so a stale/partial clone is never left behind. It is a data/config validation error in the plugin source definition, not an infrastructure failure.

Source

Thrown at packages/coding-agent/src/extensibility/plugins/marketplace/source-resolver.ts:156

		case "npm":
			throw new Error("npm plugin sources are not yet supported. Use git-based sources instead.");

		default:
			throw new Error(`Unknown plugin source type: "${(source as { source: string }).source}"`);
	}
}

// ── Helpers ─────────────────────────────────────────────────────────

async function verifyDirExists(dirPath: string, errorMessage: string): Promise<void> {
	try {
		const stat = await fs.stat(dirPath);
		if (!stat.isDirectory()) {
			throw new Error(errorMessage);
		}
	} catch (err) {
		if (isEnoent(err)) {
			throw new Error(errorMessage);
		}
		throw err;
	}
}

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the repository at the pinned branch/commit and correct `source.path` to the actual directory that exists (case-sensitive).
  2. Point `path` at a directory, not a file — the plugin manifest file should be inside the directory.
  3. If pinning a `sha`, update the pin to a commit where the subdirectory exists (e.g. the latest commit on the plugin's branch).
  4. If you control the plugin repo, restore/recreate the directory at the referenced path or publish a corrected marketplace catalog entry.

Example fix

// before
{ "source": "git", "repo": "acme/plugins", "path": "plugin/my-tool" }
// after (actual repo layout is plugins/my-tool)
{ "source": "git", "repo": "acme/plugins", "path": "plugins/my-tool" }
Defensive patterns

Strategy: validation

Validate before calling

import * as fs from "node:fs/promises";
async function gitSubdirSourceLooksValid(repoDir: string, sourcePath: string) {
	try {
		return (await fs.stat(path.join(repoDir, sourcePath))).isDirectory();
	} catch {
		return false;
	}
}

Type guard

function isNonEmptyRelativeDir(p: string): boolean {
	return typeof p === "string" && p.length > 0 && !path.isAbsolute(p) && !p.endsWith("/") && !p.includes("..");
}

Try / catch

try {
	const resolved = await resolveObjectSource(source);
} catch (err) {
	if (err instanceof Error && err.message.includes('does not exist in cloned repository')) {
		// surface source.path + repo so the user can fix the marketplace entry
		throw new Error(`Plugin source path "${source.path}" not found in ${source.repo} at the pinned branch/commit`);
	}
	throw err;
}

Prevention

When it happens

Trigger: Resolving a plugin source `{ source: "git", path: "..." }` where (1) the `path` is misspelled or uses the wrong case relative to the actual repo layout, (2) the subdirectory was renamed or deleted in the branch/commit being cloned, (3) `path` points at a file (e.g. a plugin.json) instead of a directory, or (4) the `sha`/branch pins an older commit where the directory did not yet exist.

Common situations: A marketplace.json author publishes a plugin entry pointing at `plugins/foo` but the repo layout is `plugin/foo`; a plugin moves directories in a refactor and pinned `sha` values in user configs still reference the old layout; users hand-edit a marketplace catalog path with a trailing filename; typos like `./src/plugin` vs `src/plugin`.

Related errors


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