Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

`Server.__repr__` hard-codes `/tmp/tmux-<euid>/default`, ignoring `$TMUX_TMPDIR`

Open
#723 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
72/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Quiet
Tech stack
python
Domain
cli

Research direction

Start in src/libtmux/server.py at Server.repr and Server.init, then compare the TMUX_TMPDIR handling in src/libtmux/pytest_plugin.py and the environment helpers in src/libtmux/_internal/env.py. Add a regression test using monkeypatch to set TMUX_TMPDIR and verify the repr does not name a path outside it.

Written by the indexing model from the issue text.

Description

Filed against tmux-python/libtmux v0.62.0. Found while writing tested documentation examples: the repr appeared in a pytest failure banner and named a socket the object was not talking to.

What happens

Server.__repr__ falls through to a hard-coded /tmp/tmux-<euid>/default when both socket_name and socket_path are None. tmux does not hard-code that path — it resolves the socket directory from $TMUX_TMPDIR, or /tmp when that is unset. TMPDIR is not consulted — man tmux: "the sockets are all created in a directory tmux-UID under the directory given by TMUX_TMPDIR or in /tmp", confirmed empirically on tmux 3.7b (TMPDIR=$t tmux still lands in /tmp/tmux-1000/default). So under any TMUX_TMPDIR (test harnesses, sandboxes, containers, anyone with TMUX_TMPDIR exported in their shell profile) the repr names a socket the object is not using.

        return (
            f"{self.__class__.__name__}(socket_path=/tmp/tmux-{os.geteuid()}/default)"
        )

This is a display bug, not a behaviour bug — the object talks to the right socket. But repr is what shows up in tracebacks, pytest --showlocals banners, logs, and print(server), which is exactly where someone is trying to work out which server they are looking at.

Recreation

import os, tempfile
os.environ["TMUX_TMPDIR"] = tempfile.mkdtemp(prefix="repro-")
from libtmux.server import Server

server = Server()
server.new_session(session_name="demo")
print("repr(server)      :", repr(server))
print("actual socket_path:", server.cmd("display-message", "-p", "#{socket_path}").stdout[0])
server.kill()

Observed on libtmux v0.62.0 / tmux 3.7b:

repr(server)      : Server(socket_path=/tmp/tmux-1000/default)
actual socket_path: /tmp/repro-pa15_hfr/tmux-1000/default

Expected: a repr that either names the real socket, or does not claim to know it.

Why the fall-through is reachable at all

Server.__init__ only assigns socket_path when the caller passes it, so a bare Server() has socket_name is None and socket_path is None and always lands in this branch.

That is the same root cause as #704 item 1 (the TMUX_TMPDIR-based socket_path derivation in __init__ being unreachable dead code). If #704 is fixed by repairing that derivation, socket_path becomes populated and this branch stops being reached for the common case — but the branch is still wrong and should not survive as a fallback.

What a fix needs

Pick one, in descending order of preference:

  1. Resolve the path the way tmux does and use it: socket directory is $TMUX_TMPDIR, else /tmp, then tmux-<euid>/<socket_name or "default">. This also gives socket_path a correct value to return generally, and overlaps with #704.
  2. Do not guess. Render Server(socket_path=None) or just Server() when neither attribute is set. Honest, and cheap.

Note that libtmux already computes this, in the one place that needed it:

    # ``Server(socket_name=...)`` does not populate ``socket_path`` --
    # the Server class only derives the path when neither ``socket_name``
    # nor ``socket_path`` was supplied. Recompute the location tmux uses
    tmux_tmpdir = pathlib.Path(os.environ.get("TMUX_TMPDIR", "/tmp"))
    socket_path = tmux_tmpdir / f"tmux-{os.geteuid()}" / socket_name

So the fix is less "write new logic" than "lift the logic the test plugin was forced to write into somewhere Server can use it too". src/libtmux/_internal/env.py already owns the tmux-environment readers and is the natural home.

Whichever is chosen, add a regression test that sets TMUX_TMPDIR via monkeypatch and asserts the repr does not contain a path outside it. Note the existing repr has a second oddity worth cleaning up in the same pass: the socket_name branch uses getattr(self, 'socket_name', 'default') even though it has already established self.socket_name is not None.

Dominant language
Python
Stars
1.2k
Forks
127
Avg merge
2h 13m
Merged PRs (30d)
1

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from tmux-python/libtmux

All issues in tmux-python/libtmux

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.