Plugin cache writes output directories inside cloned repo, causing recursive ENAMETOOLONG
Environment:
- Claude Code (macOS Darwin 25.3.0)
- Plugin: marketplace plugin from GitHub repo (
luqrahq/luqra-skills)
Description:
When caching a marketplace plugin, the cacher clones the source repo and then creates plugin-specific subdirectories (e.g., task-mgr/1.0.6/) inside the cloned repo's directory. On subsequent cache operations, these output directories are treated as repo contents and get re-cached recursively until hitting the OS path length limit.
Cache structure observed:
~/.claude/plugins/cache/luqra-skills/
├── README.md ← cloned repo contents
├── docs/
├── project-registry.yaml
├── skills/
└── task-mgr/ ← plugin cache output, co-located with repo contents
└── 1.0.6/
├── .claude/ ← cloned repo contents (again)
├── docs/
├── project-registry.yaml
└── task-mgr/ ← recursive: cache output inside its own output
└── 1.0.6/
└── task-mgr/
└── 1.0.6/
└── ... (repeats ~55 times, paths reach 1011 chars)
Error on plugin load:
Failed to download/cache plugin task-mgr: ENAMETOOLONG: name too long, open
Root cause:
The plugin cache output directory is written inside the cloned repo tree. The cacher doesn't exclude its own output directories when reading the repo contents, so it copies them into the next cache layer recursively.
This affects any plugin name — the name itself doesn't matter. We tested with luqra-skills, luqra-task-manager, and task-mgr and all eventually produce the same recursion.
Reproduction:
- Create a GitHub repo with
.claude-plugin/marketplace.jsonlisting plugins - Add the repo as a marketplace in Claude Code
- Install one of the listed plugins
- Run
/reload-pluginsa few times - Observe recursive directories in
~/.claude/plugins/cache/{marketplace}/{plugin-name}/
Expected behavior:
Plugin cache output should be written to a location separate from the cloned repo contents, or the cacher should exclude its own output directories when copying.
Suggested fix:
Either:
- Clone to a temp directory, copy needed files to the cache location (don't cache in-place)
- Or add the cache output path to an exclusion list when traversing repo contents
Workaround:rm -rf ~/.claude/plugins/cache/{marketplace} before each reload. The recursion rebuilds on the next cache operation.
4 Comments
Great root cause analysis. The fix is clear — the cache output directory should be written outside the cloned repo tree, not inside it.
Workaround until this is fixed:
Clear the recursive cache and manually restructure:
Alternatively, you could add a
.gitignoreor exclusion marker in the plugin cache directory, but that only helps if the cacher respects it — which it apparently doesn't since it's not doing a git clone on subsequent runs but rather a filesystem copy.The proper fix would be either:
~/.claude/plugins/cache/<plugin-name>/<version>/as a sibling to the repo clone, not inside itCan confirm, experiencing the same.
Still hitting this on 2.1.94 with
directory-source marketplaces.Observed: Same recursive nesting pattern as the original report. Cache refresh copies the output directory into itself:
Workaround:
rm -rf ~/.claude/plugins/cache/<marketplace>before each session. The recursion rebuilds on the next cache operation, same as noted in the original report.Note on directory-source marketplaces for local dev: Even without the recursion bug,
directory-source marketplaces don't provide a live link to local files. The plugin system still clones from the URL inmarketplace.jsoninto the cache — changes to local files aren't picked up until you reinstall. For iterative local plugin development,claude --plugin-dir .is the better path since it reads directly from the working directory with no caching layer.That said, the recursion bug still matters — it blocks installing from any marketplace that happens to be checked out locally, even for one-time installs.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.