April 13, 2026 • Version: 2026.4.11

macOS Gateway Service Entrypoint Mismatch Between Install and Doctor

The OpenClaw gateway service install writes a LaunchAgent plist with 'dist/entry.js' as the entrypoint, while the doctor audit expects 'dist/index.js', causing persistent service repair failures on macOS.

🔍 Symptom

On macOS systems running OpenClaw 2026.4.11, the following observable symptoms indicate the gateway service entrypoint mismatch:

  • Doctor warning: Running openclaw doctor --non-interactive --deep produces a warning stating:
    Gateway service entrypoint does not match the current install. (/opt/homebrew/lib/node_modules/openclaw/dist/entry.js -> /opt/homebrew/lib/node_modules/openclaw/dist/index.js)
  • Install behavior: Executing openclaw gateway install --force writes or overwrites the LaunchAgent plist (~/Library/LaunchAgents/ai.openclaw.gateway.plist) with ProgramArguments[1] set to /opt/homebrew/lib/node_modules/openclaw/dist/entry.js
  • Doctor expectation: The doctor audit validates against /opt/homebrew/lib/node_modules/openclaw/dist/index.js
  • Service recovery failure: After a system restart or openclaw gateway restart, the service may remain in a degraded state because restart preserves the existing plist rather than regenerating it
  • Persistent instability: Repeated reinstalls or updates do not resolve the mismatch automatically

🧠 Principle

The root cause is an internal inconsistency within OpenClaw's gateway service management logic:

  • Divergent entrypoint constants: The gateway install command references one canonical entrypoint path (dist/entry.js), while the doctor audit logic validates against a different canonical path (dist/index.js). Neither path is dynamically resolved from the actual installed artifact.
  • Plist preservation during restart: The openclaw gateway restart command does not regenerate the LaunchAgent plist; it only kickstarts the existing service. If the plist contains the wrong entrypoint, the service continues to load the incorrect binary.
  • Missing shim detection: In some affected environments, the /opt/homebrew/bin/openclaw shim is absent, which can exacerbate startup failures and mask the underlying entrypoint mismatch.
  • Bootstrap ambiguity: The recovery message "Gateway LaunchAgent was installed but not loaded; re-bootstrapped launchd service" suggests that the service installation and service loading phases are not fully synchronized, allowing the malformed plist to persist.

This is a configuration consistency defect rather than a runtime code error: the service binary exists at both paths, but the operational tooling requires a single authoritative reference.

🛠️ Fix

Apply the following steps in sequence to resolve the entrypoint mismatch:

  1. Identify the current plist entrypoint:
    defaults read ~/Library/LaunchAgents/ai.openclaw.gateway.plist ProgramArguments | tr ' ' '\n' | tail -1
  2. Stop the existing LaunchAgent:
    launchctl unload ~/Library/LaunchAgents/ai.openclaw.gateway.plist
  3. Update the entrypoint in the plist to the canonical path:
    Edit ~/Library/LaunchAgents/ai.openclaw.gateway.plist and change ProgramArguments[1] from:
    /opt/homebrew/lib/node_modules/openclaw/dist/entry.js
    to:
    /opt/homebrew/lib/node_modules/openclaw/dist/index.js
  4. Verify the corrected plist:
    defaults read ~/Library/LaunchAgents/ai.openclaw.gateway.plist ProgramArguments
    Ensure the last element in the array is /opt/homebrew/lib/node_modules/openclaw/dist/index.js
  5. Reload the LaunchAgent:
    launchctl load ~/Library/LaunchAgents/ai.openclaw.gateway.plist
  6. Verify service health:
    openclaw gateway status --deep
    The output should report a healthy gateway state with no entrypoint warnings.
  7. Confirm doctor audit passes:
    openclaw doctor --non-interactive --deep
    Verify that the entrypoint mismatch warning no longer appears.

Preventive measure: If the shim is missing, reinstall it with:

  • brew link --force openclaw (if installed via Homebrew)
  • Or ensure /opt/homebrew/bin/openclaw is symlinked to the correct Node module executable