thedotmack/claude-mem · error

Cannot lazy-spawn worker: worker-service.cjs not found in pl

Error message

Cannot lazy-spawn worker: worker-service.cjs not found in plugin/scripts

What it means

Lazy-spawn resolved the Bun runtime but resolvedScript.scriptPath is null — worker-service.cjs was not found under plugin/scripts for the current installation. The spawn aborts (returns false) and the hook event degrades, since there is no worker binary to launch.

Source

Thrown at src/shared/worker-utils.ts:557

        pid: stalePidInfo.pid,
        port: getWorkerPort(),
      });
      return false;
    }
    // The killed worker's PID file is left behind; the successor's boot
    // removes it (validateWorkerPidFile returns 'stale' for a dead pid).
    // Fall through to (re)spawn + readiness wait below.
  }

  const runtimePath = resolveWorkerRuntimePath();
  const scriptPath = resolvedScript?.scriptPath ?? null;

  if (!runtimePath) {
    logger.warn('SYSTEM', 'Cannot lazy-spawn worker: Bun runtime not found on PATH');
    return false;
  }
  if (!scriptPath) {
    logger.warn('SYSTEM', 'Cannot lazy-spawn worker: worker-service.cjs not found in plugin/scripts');
    return false;
  }

  // Spawn gate (worker-spawn-gate.ts): only ONE gated launcher — hook, MCP
  // server, or the CLI restart fallback — may spawn at a time. (The dying
  // worker's restart handoff in worker-shutdown.ts is deliberately NOT gated:
  // it is the spawner for CLI-initiated restarts. Hook version recycles never
  // trigger it — they SIGKILL the stale worker and spawn here.)
  // Losing the lock never fails the hook; the loser skips its spawn and waits
  // for the winner's worker on the existing port/readiness waits below. The
  // winner holds the lock through the port-open wait (the spawn isn't "done"
  // until the worker owns the port) and releases in finally on every exit
  // path.
  const spawnLockHeld = acquireSpawnLock();
  try {
    if (spawnLockHeld) {
      logger.info('SYSTEM', 'Worker not running — lazy-spawning', { runtimePath, scriptPath });

View on GitHub (pinned to 8bc631a71a)

Solutions

  1. Run npm run build-and-sync in the claude-mem checkout — it rebuilds and syncs plugin scripts to the installed location.
  2. Verify plugin/scripts/worker-service.cjs exists in the installed plugin (~/.claude/plugins/marketplaces/thedotmack/…).
  3. If the marketplace copy is broken, reinstall the plugin from source.
Defensive patterns

Strategy: validation

Validate before calling

if (!existsSync(path.join(pluginDir, 'scripts', 'worker-service.cjs'))) {
  // run the build before hooks try to lazy-spawn
  failEarlyWithHint('Run npm run build-and-sync');
}

Type guard

const hasWorkerScript = (resolved: { scriptPath: string | null } | null): resolved is { scriptPath: string } =>
  resolved?.scriptPath != null;

Prevention

When it happens

Trigger: The plugin install is incomplete: build artifacts never synced, scripts directory missing after an in-place upgrade, or version resolution unable to locate worker-service.cjs for the resolved plugin version.

Common situations: Cloning the repo without running the build; a partial plugin update leaving plugin/scripts empty; marketplace sync deleting files mid-update.

Related errors


AI-assisted analysis of thedotmack/claude-mem@8bc631a71a (2026-08-20). Data as JSON: /api/errors/731be39973246857. Report an issue: GitHub.