You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SessionStart/UserPromptSubmit hooks hard-crash with MODULE_NOT_FOUND when a sibling hook file is missing — bare top-level require('./caveman-config') in 3 of 4 entrypoints #848
SessionStart:startup hook error
Failed with non-blocking status code: node:internal/modules/cjs/loader:1408
Root cause is a missing sibling file (src/hooks/caveman-config.js) in the installed plugin dir. But the reason it surfaces as an opaque loader stack trace instead of a diagnosable message is a code issue in caveman: 3 of the 4 hook entrypoints require ./caveman-config at top level with no guard, so any missing/unreadable sibling turns into an uncaught MODULE_NOT_FOUND and exit 1 on every SessionStart and every UserPromptSubmit.
And caveman-activate.js itself demonstrates the fail-soft philosophy 18 lines further down (L30-33), for the optional dep:
// Best-effort: any error is swallowed so SessionStart is never blocked.try{const{ applyOverrides, resolvePluginRoot }=require('./cavecrew-model-overrides');applyOverrides(resolvePluginRoot(__dirname));}catch(e){}
So the codebase already treats "a sibling hook file may be absent" as a real risk — it just guards one of the four call sites. This is the same failure class as #801 (install.sh/install.ps1 omitting caveman-parse.js); that fix added the file to the copy list, but the underlying "top-level require ⇒ hard crash" remains, so the next missing file reproduces it.
How the file went missing
I could not attribute the deletion, and I am not claiming caveman deleted it — reporting the observed state in case it is a known install-path problem:
The installed plugin dir is a git worktree at the exact HEAD commit, and git reports the file as deleted from the worktree only:
$ git -C ~/.claude/plugins/cache/caveman/caveman/27d5a3981a34 status --porcelain D src/hooks/caveman-config.js D src/mcp-servers/caveman-shrink/README.md D src/mcp-servers/caveman-shrink/compress.js D src/mcp-servers/caveman-shrink/index.js D src/mcp-servers/caveman-shrink/package.json D src/mcp-servers/caveman-shrink/spawn-options.js D src/rules/caveman-activate.md D src/rules/caveman-openclaw-bootstrap.md?? .in_use/
Exactly 8 tracked files, all under src/, all present at HEAD (git ls-tree HEAD src/hooks/ lists caveman-config.js, blob d94131b, and the blob is present in .git/objects). Not sparse-checkout (fatal: this worktree is not sparse), not gitignored (git check-ignore exits 1 for all three paths). The marketplace clone at ~/.claude/plugins/marketplaces/caveman has all 8 files. Other cached version dirs for the same 2.0.0 release (613d7f0402fb, a0109974ea32, c72984e4392c, 099327780ef6) all have caveman-config.js; only the current 27d5a3981a34 does not. git status on this worktree shows no other drift, so it is not a broad truncation.
Note that src/hooks/checksums.sha256already listscaveman-config.js — the manifest that would have caught this ships with the plugin, but nothing verifies it at runtime.
Emit one actionable line on stderr instead of a Node stack trace, e.g. caveman: plugin install incomplete (missing caveman-config.js) — run /plugin update caveman.
Optionally verify src/hooks/checksums.sha256 on SessionStart (cheap, manifest already shipped) so a partial install self-reports instead of failing at a random require.
Environment
Claude Code 2.1.233, plugin install path (.claude-plugin/plugin.json hooks), not standalone install.sh
Every session start prints:
Root cause is a missing sibling file (
src/hooks/caveman-config.js) in the installed plugin dir. But the reason it surfaces as an opaque loader stack trace instead of a diagnosable message is a code issue in caveman: 3 of the 4 hook entrypoints require./caveman-configat top level with no guard, so any missing/unreadable sibling turns into an uncaughtMODULE_NOT_FOUNDand exit 1 on every SessionStart and every UserPromptSubmit.Reproduction
The code issue
src/hooks/caveman-activate.jsL12 — mandatory dependency, unguarded:Same shape in
src/hooks/caveman-mode-tracker.jsL9 andsrc/hooks/caveman-stats.jsL13.src/hooks/caveman-parse.jsL43-48 already does the right thing for the identical import:And
caveman-activate.jsitself demonstrates the fail-soft philosophy 18 lines further down (L30-33), for the optional dep:So the codebase already treats "a sibling hook file may be absent" as a real risk — it just guards one of the four call sites. This is the same failure class as #801 (
install.sh/install.ps1omittingcaveman-parse.js); that fix added the file to the copy list, but the underlying "top-level require ⇒ hard crash" remains, so the next missing file reproduces it.How the file went missing
I could not attribute the deletion, and I am not claiming caveman deleted it — reporting the observed state in case it is a known install-path problem:
The installed plugin dir is a git worktree at the exact HEAD commit, and git reports the file as deleted from the worktree only:
Exactly 8 tracked files, all under
src/, all present at HEAD (git ls-tree HEAD src/hooks/listscaveman-config.js, blobd94131b, and the blob is present in.git/objects). Not sparse-checkout (fatal: this worktree is not sparse), not gitignored (git check-ignoreexits 1 for all three paths). The marketplace clone at~/.claude/plugins/marketplaces/cavemanhas all 8 files. Other cached version dirs for the same 2.0.0 release (613d7f0402fb,a0109974ea32,c72984e4392c,099327780ef6) all havecaveman-config.js; only the current27d5a3981a34does not.git statuson this worktree shows no other drift, so it is not a broad truncation.Note that
src/hooks/checksums.sha256already listscaveman-config.js— the manifest that would have caught this ships with the plugin, but nothing verifies it at runtime.Workaround that fixed it locally:
Suggested fix
caveman-parse.jsalready does — a hook must never exit non-zero because a sibling is missing. On failure, degrade to the built-in fallback ruleset (as Plugin install: SKILL.md lookup resolves to nonexistent src/skills/, hook silently degrades to fallback ruleset #792 describes for the SKILL.md lookup) rather than crashing.caveman: plugin install incomplete (missing caveman-config.js) — run /plugin update caveman.src/hooks/checksums.sha256on SessionStart (cheap, manifest already shipped) so a partial install self-reports instead of failing at a random require.Environment
.claude-plugin/plugin.jsonhooks), not standaloneinstall.sh27d5a3981a34("README: whole-cave table gains status column, Browse row, frozen tier")Related: #801 (same failure class, standalone installer), #792 (missing-file path degrading silently), #78 / #471 (same loader error, different root cause — path resolution / orphaned hooks).