thedotmack/claude-mem · warning

Worker failed to start before hook, handler will proceed gra

Error message

Worker failed to start before hook, handler will proceed gracefully

What it means

Before dispatching a hook event (context, observation, summarize, ...), the hook command calls ensureWorkerStarted(). If that returns 'dead' — spawn failed, Windows cooldown skip, or port conflict without health — this warning fires. The hook then proceeds without the worker, so this event's memory capture is skipped rather than blocking the user's session.

Source

Thrown at src/services/worker-service.ts:1332

    case 'hook': {
      // IO discipline: this case is the entry point to the hook execution path.
      // Once hookCommand is invoked, src/shared/hook-io.ts owns all
      // stdout/stderr/exit. The pre-hookCommand error paths below (missing args,
      // worker failed to start) are CLI-style: console.error + exit 1 is
      // acceptable because they occur BEFORE the buffered window opens.
      const platform = process.argv[3];
      const event = process.argv[4];
      if (!platform || !event) {
        console.error('Usage: claude-mem hook <platform> <event>');
        console.error('Platforms: claude-code, codex, cursor, antigravity-cli, raw');
        console.error('Events: context, session-init, observation, summarize, user-message');
        process.exit(1);
      }

      const workerStartResult = await ensureWorkerStarted(port);
      if (workerStartResult === 'dead') {
        logger.warn('SYSTEM', 'Worker failed to start before hook, handler will proceed gracefully');
      }

      const { hookCommand } = await import('../cli/hook-command.js');
      await hookCommand(platform, event);
      break;
    }

    case 'generate': {
      const dryRun = process.argv.includes('--dry-run');
      const { generateClaudeMd } = await import('../cli/claude-md-commands.js');
      const result = await generateClaudeMd(dryRun);
      process.exit(result);
      break;
    }

    case 'clean': {
      const dryRun = process.argv.includes('--dry-run');
      const { cleanClaudeMd } = await import('../cli/claude-md-commands.js');

View on GitHub (pinned to e2d1df569a)

Solutions

  1. Run `claude-mem start` manually and read the worker log to see the actual spawn failure
  2. On Windows, wait out the 2-minute spawn cooldown before retrying (or delete the cooldown marker once the root cause is fixed)
  3. Free the occupied port or move claude-mem to another one, then retry the hook-triggering action
Defensive patterns

Strategy: fallback

Validate before calling

const result = await ensureWorkerStarted(port);
if (result === 'dead') {
  // proceed without worker; schedule a manual start instead of retrying in the hot path
  console.warn('worker unavailable — hook will run without memory capture');
}

Prevention

When it happens

Trigger: Worker spawn fails (missing runtime, permissions, antivirus on Windows); shouldSkipSpawnOnWindows() suppresses spawn within the 2-minute cooldown after a prior failure; port occupied by a non-worker process.

Common situations: Windows machines where a previous spawn failed and hooks keep firing inside the cooldown; broken node/bun install; corporate security software blocking the daemon; disk-full preventing log/db writes at startup.

Related errors


AI-assisted analysis of thedotmack/claude-mem@e2d1df569a (2026-08-20). Data as JSON: /api/errors/31fac0b4192089a9. Report an issue: GitHub.