Mid-session plugin update leaves session in mixed state: new hook definitions resolve against the old ${CLAUDE_PLUGIN_ROOT} cache until restart
Summary
Updating a plugin mid-session (via the interactive /plugin flow) leaves the live session in a mixed state: the new version's skill and hook definitions register immediately, but ${CLAUDE_PLUGIN_ROOT} keeps resolving to the old version's cache directory for the rest of the session. If the new version's hooks.json references a file that didn't exist in the old version's cache, every hook firing errors until the session is restarted.
Observed on Claude Code CLI 2.1.211 (Windows 11, Node v24.12.0) while updating the tandem plugin (marketplace DATA-AI-XYZ/Tandem) from 1.1.0 → 2.7.0 inside a live session. The two versions renamed the hook entrypoint (hook-runner.js → hook.js), which guaranteed the miss.
Steps to reproduce
- Start a session with plugin version A active, where version B (a newer release) renames or adds a file referenced by
hooks.json. - Mid-session, run
/plugin→ update the marketplace → update the plugin to version B. - Continue working; let the session reach a hook event (e.g. Stop).
- Observe: the new (version B) hook definition fires, but
${CLAUDE_PLUGIN_ROOT}still points at version A's cache path, so the referenced entrypoint doesn't exist there.
Actual behaviour
Stop hook error … Cannot find module '~\.claude\plugins\cache\DATA-AI-XYZ\tandem\1.1.0\_00-Project-Management\93-Scripts\hook.js'
installed_plugins.json(post-update): installPath…\tandem\2.7.0, version 2.7.0 — the pin updated correctly.…\cache\…\2.7.0\…\hook.jsexists; the 1.1.0 cache never shipped that file.- Non-blocking (session continues), but the error repeats on every hook event until restart, which reads as alarming breakage to a user mid-upgrade.
Expected behaviour
Either of these would be coherent:
- The session keeps running the old version's complete component set (definitions + root) until restart, or
${CLAUDE_PLUGIN_ROOT}re-resolves together with the refreshed definitions.
At minimum, the /plugin update flow could surface a "restart your session to finish the update" notice so the transient errors are expected rather than mysterious.
What we ship as a workaround (plugin-author side)
- Docs: our README "Updating" section and the update skill now tell users to restart after a plugin update, and that hook errors mentioning the old version's path are expected and harmless until then.
- Compatibility: we ship a small forwarding stub under the old entrypoint name so stale hook definitions keep working against new caches — but the observed direction (new definitions against an old cache) can't be guarded from the plugin side, since old caches can't be retro-populated.
Happy to provide more detail if useful.