Skip to content

bug: session-end hook causes 'Hook cancelled' due to .unref() making setTimeout passive while fetch keeps event loop alive #1069

Description

@dnraitzyk

Bug

When closing Claude Code, users intermittently see:

SessionEnd hook [node "${CLAUDE_PLUGIN_ROOT}/scripts/session-end.mjs"] failed: Hook cancelled

Root cause

session-end.mjs fires fire-and-forget fetch() calls to the local daemon and then does:

setTimeout(() => process.exit(0), 1500).unref();

The intent (per AGENTS.md) is that the process force-exits after 1500ms so it does not block Claude Code's shutdown. But .unref() makes the timer passive — it does not prevent process exit, but it also does not force it. Node.js keeps the event loop alive as long as there are pending network requests, and the in-flight fetch() calls do exactly that.

Result: the process stays alive until the fetches complete or their AbortSignal timeouts fire:

  • /agentmemory/session/end: up to 30s
  • /agentmemory/crystals/auto (when CONSOLIDATION_ENABLED=true): up to 60s
  • /agentmemory/consolidate-pipeline (when CONSOLIDATION_ENABLED=true): up to 120s

Claude Code's hook timeout fires before the fetches settle and kills the process with Hook cancelled.

The bug is intermittent because when the daemon responds quickly the hook exits in time; when it is slow or busy the race is lost.

Fix

Remove .unref() from the setTimeout. An active (ref'd) timer keeps the event loop alive and guarantees the process exits after exactly 1500ms regardless of in-flight fetches. Since the fetches are fire-and-forget to a local daemon, exiting before they settle is the correct and intended behavior — matching what AGENTS.md documents.

- setTimeout(() => process.exit(0), 1500).unref();
+ setTimeout(() => process.exit(0), 1500);

Fix is in PR #1070.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions