can1357/oh-my-pi · error · Error
Relative plugin source paths must start with "./" — got: "${
Error message
Relative plugin source paths must start with "./" — got: "${source}" What it means
resolveRelativeSource() handles plugin sources that are paths relative to the marketplace clone (e.g. "./plugins/foo"). It strictly requires the "./" prefix so a bare relative path can't be confused with a plugin name, git URL, or other source kind routed by resolvePluginSource. Any relative-looking source without the prefix throws this error.
Source
Thrown at packages/coding-agent/src/extensibility/plugins/marketplace/source-resolver.ts:56
context: ResolveContext,
): Promise<{ dir: string; tempCloneRoot?: string }> {
const { source } = entry;
if (typeof source === "string") {
return resolveRelativeSource(source, context);
}
return resolveObjectSource(source, context);
}
// ── Relative string source ("./plugins/foo") ────────────────────────
async function resolveRelativeSource(
source: string,
context: ResolveContext,
): Promise<{ dir: string; tempCloneRoot?: string }> {
if (!source.startsWith("./")) {
throw new Error(`Relative plugin source paths must start with "./" — got: "${source}"`);
}
if (!context.marketplaceClonePath) {
throw new Error(`Cannot resolve relative source "${source}": marketplaceClonePath is required`);
}
// If pluginRoot is set, prepend it to the path segment after "./"
const pluginRoot = context.catalogMetadata?.pluginRoot;
const relativePath = pluginRoot ? `./${path.join(pluginRoot, source.slice(2))}` : source;
// Resolve against marketplace root (not the .claude-plugin/ catalog subdirectory)
const resolved = path.resolve(context.marketplaceClonePath, relativePath);
if (!pathIsWithin(context.marketplaceClonePath, resolved)) {
throw new Error(
`Plugin source "${source}" resolves outside marketplace root ("${context.marketplaceClonePath}")`,
);
}View on GitHub (pinned to 9690622007)
Solutions
- Prefix the source with "./" in the catalog entry: "./plugins/foo"
- Ensure the path is relative to the marketplace root (pluginRoot is applied automatically) — not absolute or ".."-based
- Re-run /marketplace update after fixing the catalog so the corrected entry is fetched
- If authoring a catalog, validate every plugin source starts with "./"
Example fix
// before (catalog entry)
{"name": "foo", "source": "plugins/foo"}
// after
{"name": "foo", "source": "./plugins/foo"} Defensive patterns
Strategy: validation
Validate before calling
function isRelativePluginSource(source) {
return typeof source === 'string' && source.startsWith('./') && !source.slice(2).includes('..');
}
if (!isRelativePluginSource(entry.source)) throw new Error(`source must start with "./": ${entry.source}`); Type guard
const isDotRelativeSource = (v) => typeof v === 'string' && v.startsWith('./'); Try / catch
try {
const dir = await resolvePluginSource(source, ctx);
} catch (err) {
if (err.message.startsWith('Relative plugin source paths must start with')) {
console.error(`Fix the catalog entry: "${source}" → "./${source}"`);
} else throw err;
} Prevention
- When authoring catalogs, always write plugin sources as "./path" relative to the marketplace root
- Add a lint/check step over catalog JSON validating the "./" prefix
- Don't copy path conventions from other plugin ecosystems that allow bare relative paths
- Avoid ".." segments; use pluginRoot metadata for nested layouts
When it happens
Trigger: A marketplace catalog entry declares a plugin source like "plugins/foo" or "../shared/foo" instead of "./plugins/foo"; hand-written catalog JSON omitting the "./"; programmatic resolvePluginSource calls passing a raw relative path.
Common situations: Authoring a custom marketplace catalog and forgetting the "./" convention; copying path strings from docs or other plugin systems that allow bare relative paths; paths containing ".." segments that also violate the prefix rule.
Related errors
- pluginClass must be a MnemopiPlugin subclass
- Plugin '${name}' is already registered
- Unsupported language '{value}'. Supported: {}
- Unable to infer language from file extension: {}. Specify `l
- Invalid pattern: {err}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/b9db106f6ff21db2.
Report an issue: GitHub.