can1357/oh-my-pi · error · Error
npm plugin sources are not yet supported. Use git-based sour
Error message
npm plugin sources are not yet supported. Use git-based sources instead.
What it means
resolveObjectSource has an explicit case for npm plugin sources that is a hard rejection: npm registry packages are not implemented as a plugin source type in this marketplace resolver yet, so any entry declaring { source: "npm", ... } is refused immediately with a directive to use git-based sources. Unlike the unknown-type case this is a known but unimplemented source, so the error is deterministic and not a typo indicator.
Source
Thrown at packages/coding-agent/src/extensibility/plugins/marketplace/source-resolver.ts:139
timeoutMs: GIT_CLONE_TIMEOUT_MS,
});
const subdirPath = path.resolve(cloneDir, source.path);
if (!pathIsWithin(cloneDir, subdirPath)) {
await fs.rm(cloneDir, { recursive: true, force: true });
throw new Error(`git-subdir path "${source.path}" escapes the cloned repository`);
}
try {
await verifyDirExists(subdirPath, `git-subdir path "${source.path}" does not exist in cloned repository`);
} catch (err) {
await fs.rm(cloneDir, { recursive: true, force: true });
throw err;
}
return { dir: subdirPath, tempCloneRoot: cloneDir };
}
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);
}View on GitHub (pinned to 9690622007)
Solutions
- Replace the npm source with a git-based equivalent: { "source": "github", "repo": "owner/repo" } or { "source": "url", "url": "https://host/repo.git" }, optionally with ref/sha pinning.
- If the package exists only on npm, find or create its git repository (many npm packages link one) and reference that instead.
- Use source "git-subdir" with url + path if the plugin lives in a subdirectory of a monorepo.
- Track/watch upstream support for npm sources if you truly need registry-based plugins; until then no configuration change makes npm sources work.
Example fix
// before
{ "name": "my-plugin", "source": "npm", "package": "my-plugin" }
// after
{ "name": "my-plugin", "source": "github", "repo": "owner/my-plugin" } Defensive patterns
Strategy: validation
Validate before calling
function usesUnsupportedNpmSource(entry: { source: unknown }): boolean {
return typeof entry.source === "object" && entry.source !== null
&& (entry.source as { source?: unknown }).source === "npm";
}
// filter or rewrite these entries before invoking the resolver Type guard
function isNpmPluginSource(source: unknown): source is { source: "npm" } {
return typeof source === "object" && source !== null
&& (source as { source?: unknown }).source === "npm";
} Try / catch
try {
const { dir } = await resolvePluginSource(entry, context);
} catch (err) {
if (err instanceof Error && err.message.startsWith("npm plugin sources are not yet supported")) {
// surface a user-facing message pointing at git-based alternatives; skip the entry
} else throw err;
} Prevention
- Audit catalogs from other ecosystems (e.g. Claude Code) for npm entries before loading them here
- Always express plugins as git sources: github repo, full URL, or git-subdir
- Pin a ref/sha on git sources for reproducible installs
- Check the resolver's supported source types in source-resolver.ts docs before authoring entries
When it happens
Trigger: resolvePluginSource receives a MarketplacePluginEntry whose source object has source: "npm" — e.g. a marketplace.json copied from another tool's catalog (such as Claude Code marketplaces that support npm sources) and loaded by this resolver; or a user hand-writes an npm-based plugin entry expecting registry installation support.
Common situations: Migrating a marketplace catalog from Claude Code or another ecosystem where npm plugin sources are valid; following upstream plugin documentation that mentions npm distribution; a plugin author publishing to npm and writing { "source": "npm", "package": "my-plugin" } without checking this resolver's supported types.
Related errors
- OpenAI explicit prompt caching is unsupported for ${model.pr
- no built-in uploader or serving adapter is implemented
- Plugin source "${source}" resolves outside marketplace root
- Unknown plugin source type: "${(source as { source: string }
- Plugin source directory does not exist: "${resolved}"
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/20b61c163ea8ba4b.
Report an issue: GitHub.