Skip to content

brew upgrade leaves the old daemon running: no restart, no version-skew detection (macOS) #609

Description

@madeinoz67

Context: macOS, gortex installed via Homebrew. The formula replaces /opt/homebrew/bin/gortex, but a daemon that is already running keeps serving from the old binary indefinitely after brew upgrade. Nothing restarts it, and nothing surfaces the skew: the CLI and every MCP client keep connecting to the daemon on the old version.

Observed on my machine (v0.63.x line):

  • a daemon started days before an upgrade was still serving afterwards; gortex daemon status showed the old build while the on-disk binary was newer
  • the launchd unit exists (~/Library/LaunchAgents/com.zzet.gortex.plist) but reports not loaded, while a manually-started daemon holds the socket — so even a user who ran daemon install-service once can end up with a unit that owns nothing

Why I think this happens:

  1. A hand-started daemon (gortex daemon start) has no supervisor and no upgrade hook; swapping the binary does not touch the running process. macOS keeps executing the old inode.
  2. brew upgrade does not reload or restart launchd units. If the unit was never loaded (or the daemon was started manually anyway), there is nothing to bounce.
  3. The docs say gortex mcp exits "if no compatible daemon can be reached" — but compatibility evidently is not binary-version-level, because a new CLI drives an old daemon silently. I could not find any build-version comparison on the connect path (the protocolVersion strings I found are MCP-protocol constants).

Impact: stale graph behavior and bugfixes; mixed versions between CLI and daemon (daemon status shows one build, the binary is another); store migrations and behavior changes land late or never until someone notices and restarts by hand.

Possible directions (not prescriptions):

  1. Version-skew detection on connect: CLI/mcp proxy compares its build version against the daemon's (status already carries a version) and either refuses or prints a loud one-liner: daemon is vX, binary is vY, run gortex daemon restart.
  2. Make the restart story explicit after package-manager upgrades: a hint in brew output is formula-side, but gortex could detect its own staleness (e.g. running image vs on-disk binary) and report it in daemon status/mcp logs.
  3. Consider making the supervised service the blessed path (KeepAlive restarts after upgrade), and have daemon start warn when a launchd unit is installed but not loaded, or when a hand-started daemon is shadowing a unit.

Happy to work on a fix if any of the directions sound right.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions