| name | cc-pluginroot-directory-source-ignored |
| description | Fix for Claude Code startup error `Plugin directory not found at path:
<marketplace_root>/<plugin_name>. Check that the marketplace entry has
the correct path.` when the marketplace is a `source: "directory"`
marketplace that uses `metadata.pluginRoot` to factor out a common
prefix from plugin sources. Use when: (1) you author a local
directory-source Claude Code marketplace (registered with
`claude plugin marketplace add <local-path>`); (2) the
marketplace.json declares plugins like
`{"name":"foo","source":"./foo"}` with a top-level
`metadata.pluginRoot: "./plugins"`; (3) plugin subdirectories
physically exist at `<root>/plugins/foo` but Claude Code reports them
missing at `<root>/foo` — i.e. the `/plugins/` segment is silently
dropped from the resolved path; (4) you're managing the marketplace
via APM (`apm.yml` with `marketplace.metadata.pluginRoot:
./plugins`), APM's packaging step happily emits the `pluginRoot`-factored
marketplace.json, but Claude Code rejects it at load time;
(5) the same plugin loads fine when you change its source from
`./foo` to `./plugins/foo` and remove `pluginRoot`. Root cause: as of
Claude Code 2.1.158 the runtime resolver does NOT apply
`metadata.pluginRoot` for `source: "directory"` marketplaces — the
field is accepted by the schema (no validation error) and is honored
for `git-subdir` sources, but for directory-source marketplaces the
plugin source is resolved literally against the marketplace's
installLocation. Fix: revert to explicit `./plugins/<name>` source
paths and remove the now-unused `pluginRoot` at BOTH layers when
APM-managed (apm.yml AND marketplace.json — apm.yml is the source of
truth, marketplace.json is regenerated by APM's packaging step).
|
| author | Claude Code |
| version | 1.0.0 |
| date | 2026-05-30T00:00:00.000Z |
Claude Code directory-source marketplace: pluginRoot ignored
Problem
Claude Code refuses to load plugins from a local directory-source
marketplace and prints, for each affected plugin:
Plugin directory not found at path: <marketplace_root>/<plugin_name>.
Check that the marketplace entry has the correct path.
The directory IS present on disk — just at
<marketplace_root>/plugins/<plugin_name>, not at the resolved path
Claude Code is reporting. The marketplace.json's
metadata.pluginRoot: "./plugins" is being silently ignored.
The error message blames "the marketplace entry" but the entry is
correct per the documented schema; the bug is in the resolver.
Context / Trigger Conditions
ALL of these together strongly point at this failure mode:
- The marketplace was registered as
source: "directory" (you can
see this in ~/.claude/plugins/known_marketplaces.json — look for
"source": "directory" under the marketplace name).
- Its
marketplace.json includes "metadata": { ..., "pluginRoot": "./plugins" }.
- Plugin entries use the factored short form, e.g.
{"name": "claudeception", "source": "./claudeception"} —
relying on pluginRoot to add ./plugins/ to that path.
- Plugin subdirectories physically exist at
<root>/plugins/<name>, NOT at <root>/<name>.
- The error message shows the resolved path WITHOUT the
./plugins/ segment.
- Only some plugins from the marketplace are reported — usually
the ones currently enabled in settings or with cached install
records — but ALL plugins in the marketplace are broken at
runtime. The errors will spread to other plugins as soon as
they're consulted.
Root Cause
The Claude Code 2.1.158 binary's marketplace schema accepts
metadata.pluginRoot (validated as
h.object({pluginRoot: h.string().optional()...})). The field IS
read at multiple call sites (H.pluginRoot, v.pluginRoot,
z.pluginRoot are visible in the binary), but NONE of those call
sites are the source-resolution path for source: "directory"
marketplaces. For directory sources, the plugin source string is
joined directly against the marketplace's installLocation with no
pluginRoot prepending.
Result: a marketplace.json that validates fine at install time and
even passes APM's packaging step in mode (since APM uses the same schema)
fails at plugin-load time.