vmux
Appsvmux Daemon

Troubleshooting

Recover from socket errors, missing daemons, frozen panes, and broken configs.

This page collects the failure modes we see most often. Errors are matched against the literal string vmux: or vmuxd: prefix the binaries write to stderr, plus what you'll see at the host shell.

"no daemon running" / connectFailed(2) / connectFailed(61)

Symptom (with auto-start disabled or unable to spawn):

vmux: connectFailed(2)        # ENOENT — socket file doesn't exist
vmux: connectFailed(61)       # ECONNREFUSED — file exists, no listener

Root cause:

  1. The socket path resolved by the client is not where a daemon is listening.
  2. Auto-start is disabled in your config (client.autoStartDaemon: false) or the spawned daemon failed.
  3. There is a stale socket file from a crashed daemon.

Fix:

# Confirm what path the client is using
echo "/tmp/vmux-$(id -u).sock"     # the default
# or read it from your config
jq -r '.shared.socketPath // .client.socketPath' ~/.config/vmux/config.json

# Check whether anything is listening
lsof -U | grep vmux

# Remove stale socket, start fresh
rm -f /tmp/vmux-$(id -u).sock
vmuxd --daemonize
vmux ls

If you have autoStartDaemon off on purpose, run vmuxd --daemonize yourself or load your LaunchAgent (see Installation).

daemonLaunchFailed(…)

Symptom:

vmux: daemonLaunchFailed(vmuxd exited with status 1)

The client tried to auto-launch vmuxd but the spawn process exited non-zero. Common causes:

  • The daemon's socket path can't be bound — usually because another daemon is already listening, or the parent directory of the socket doesn't exist.
  • The daemon executable on PATH is from an older version that does not understand a flag the client passed.
  • File permissions on the socket directory.

Fix:

# Run the daemon in the foreground to see what it says
vmuxd
# or with the same flags the client would use
vmuxd --socket /tmp/vmux-$(id -u).sock

If you see vmuxd: bindFailed(48) (EADDRINUSE), another daemon already owns the socket. Either reuse it or pick a new path.

If you see vmuxd: bindFailed(13) (EACCES), the directory of the socket is not writable by you.

socketPathTooLong

Symptom:

vmux: socketPathTooLong

AF_UNIX socket paths are bounded by sun_path — about 104 characters on macOS. If your config picks a long path inside a deep directory (/Users/me/very/.../sock), the client refuses to connect.

Fix: use a shorter path. ~/.vmux/run/v.sock is plenty.

invalidConfig(…)

Symptom:

vmux: invalidConfig(/Users/me/.config/vmux/config.json: The data couldn’t be read because it is missing.)
vmux: invalidConfig(server.initialCols must be > 0)
vmux: invalidConfig(unsupported schemaVersion 2; expected 1)

The config file at the resolved path is unparseable, has an empty path string, has a non-positive size, or uses a schema version this binary does not know.

Fix:

  • Validate the JSON: jq . ~/.config/vmux/config.json.
  • Compare against Configuration file. The decoder is strict — unknown keys are rejected.
  • If you upgraded the binary and the schema bumped, regenerate the config from the documented defaults.

You can always sidestep a broken config for one invocation:

vmux --config /dev/null attach

/dev/null decodes as an empty file → empty config → built-in defaults.

"no daemon running" but one is

Symptom: vmux ls says nothing is there even though pgrep vmuxd shows a daemon.

Root cause: the client and the daemon are using different socket paths. This usually happens when one side reads a config and the other doesn't.

Fix:

# Force both sides to the same path
pkill -INT vmuxd
vmuxd --daemonize --socket /tmp/vmux-$(id -u).sock
vmux  --socket /tmp/vmux-$(id -u).sock ls

If that works, re-check that VMUX_CONFIG and your ~/.config/vmux/config.json agree, and that you didn't override one side with a stale shell alias.

Client attaches but screen is blank or stuck

Symptom: vmux attach connects, terminal goes into raw mode, but no prompt appears. Keystrokes have no effect.

Root cause: the daemon is in a bad state — usually because the configured server.shell does not exist, has the wrong permissions, or is exiting immediately.

Fix:

# Foreground the daemon to see its trace
pkill -INT vmuxd
vmuxd --shell /bin/zsh 2>&1 | tee /tmp/vmuxd.log
# in another terminal
vmux attach -s smoke

Look for [vmuxd] client attached: session=… followed by spawn errors. Adjust server.shell accordingly.

Sessions disappear after restart

This is by design. vmuxd keeps all session state in memory. When the daemon process exits — for any reason — every session is gone with it.

There is no on-disk state, no PID file, no journal. The intended way to "save your work" is to detach the client (the session keeps running) but never to kill the daemon if the work matters.

If you need persistence across reboots, the work has to live elsewhere — for example a mosh session into a remote machine, started from inside a vmux pane. Then your local daemon can come and go without affecting the remote work.

Panes don't redraw, or characters look corrupted

Symptom: parts of the screen are stale or characters get garbled when text wraps.

Causes and fixes:

  • Wrong TERM inside the pane. Run echo $TERM. Should be xterm-256color. If your config or the spawned process overrode it to something poor, fix the override or pass pane launch --env TERM=xterm-256color.
  • Synchronized output sequence misinterpreted. vmux attach emits CSI ? 2026 h and CSI ? 2026 l around redraws. Some old wrappers handle this badly. If you're inside another multiplexer, make sure that multiplexer passes the sequence through.
  • Mismatched terminal size. SIGWINCH is forwarded automatically, but virtualized terminals sometimes lie. Force a resize with tput cols; tput lines and detach/reattach if the daemon got stuck on an old size.

Color is wrong (everything is too dim or 8-color)

The CLI delegates color to whatever the running process asks for. The daemon never strips color.

If your shell looks 8-color inside a vmux pane but truecolor everywhere else, the most likely culprit is the inherited COLORTERM. Set it explicitly:

# in the spawned shell's rcfile
export COLORTERM=truecolor

Or, system-wide via the config:

{
  "schemaVersion": 1,
  "server": {
    "environment": { "COLORTERM": "truecolor" }
  }
}

vmuxd crashes

Symptom: the daemon exits unexpectedly. Clients see the socket close (Transport endpoint is not connected) and vmux attach returns.

Where to find logs:

  • Foreground. Output is on the daemon's stderr. Run as vmuxd 2>/tmp/vmuxd.log to capture.
  • launchctl-managed. Whatever path you put in StandardErrorPath. If you copied the example plist, it's /tmp/vmuxd.err.log.
  • --daemonize from the client. Stderr is redirected to /dev/null — there is no log. Re-run in the foreground to reproduce.

If you can reproduce it, run the daemon under lldb:

lldb -- vmuxd
(lldb) run
# crash here
(lldb) bt all

…and file an issue with the backtrace, the config (sanitized of secrets), and the steps to reproduce.

"unknown argument" from either binary

Symptom:

vmux: protocolError("unknown argument: --foo")
vmuxd: bindFailed(22)

Both binaries reject any flag they don't recognize. This is intentional — typos shouldn't silently change behavior. Check the canonical lists:

There is no --help output today — the flag list above is the documentation.

vmux state returns a session you didn't create

If vmux state returns a session named default you didn't explicitly make, that's the auto-creation path: the first attach (with no -s) creates the daemon's defaultSessionName, which defaults to default. Either pin it with server.defaultSessionName in your config or always pass -s NAME when attaching.

Two daemons keep coming up

Symptom: pgrep vmuxd returns two PIDs after a single vmux attach.

Cause: the client's auto-start path raced with a launchd-managed daemon. The first one to bind the socket wins; the second one fails.

Fix: turn auto-start off in the client config when you have a managed daemon:

{ "client": { "autoStartDaemon": false } }

Still stuck

When opening an issue, please include:

  • macOS version (sw_vers).
  • Output of vmux --socket /tmp/vmux-$(id -u).sock ls (or the socket you actually use).
  • Output of lsof -U | grep vmux.
  • Foreground daemon log for the failing scenario (vmuxd 2>/tmp/vmuxd.log).
  • Sanitized config file contents.

See also