Skip to content

Conversation

@tony
Copy link
Member

@tony tony commented Dec 13, 2025

Summary

Fixes an issue where Session.attach() would raise TmuxObjectDoesNotExist when a user:

  1. Attaches to a tmux session via tmuxp load
  2. Works in the session
  3. Kills the session (e.g., closes all windows) before detaching
  4. Detaches from tmux

User Experience

After running tmuxp load, users would see this traceback printed to their terminal after detaching:

Traceback (most recent call last):
  File "/home/d/.local/bin/tmuxp", line 7, in <module>
    sys.exit(cli.cli())
  ...
  File ".../libtmux/session.py", line 332, in attach
    self.refresh()
  File ".../libtmux/neo.py", line 167, in _refresh
    obj = fetch_obj(...)
  File ".../libtmux/neo.py", line 242, in fetch_obj
    raise exc.TmuxObjectDoesNotExist(...)
libtmux.exc.TmuxObjectDoesNotExist: Could not find object

Root Cause

Session.attach() called self.refresh() after the attach-session command returned. Since attach-session is a blocking interactive command, the session state can change arbitrarily during attachment - including being killed entirely.

The refresh() call was semantically incorrect for interactive commands:

  • attach-session blocks until user detaches
  • Session state can change during attachment
  • Refreshing after such a command makes no sense

Timeline

  • Feb 2024: 9a5147a - Session.attach() was added with the refresh() call
  • Nov 2025: tmuxp tmux-python/tmuxp@fdafdd2b switched from attach_session() to attach()
  • Users started experiencing the bug

Changes

  • Removes self.refresh() call from Session.attach()
  • Adds regression test using NamedTuple + parametrize + test_id pattern

Test plan

  • Existing tests/test_session.py tests pass (34 passed)
  • New regression test test_session_attach_does_not_fail_if_session_killed_during_attach passes
  • Manual verification: tmuxp load, kill session, detach - no exception

Related

@codecov
Copy link

codecov bot commented Dec 13, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 45.39%. Comparing base (64276e4) to head (9826825).
⚠️ Report is 5 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #616      +/-   ##
==========================================
+ Coverage   45.24%   45.39%   +0.15%     
==========================================
  Files          22       22              
  Lines        2250     2249       -1     
  Branches      360      360              
==========================================
+ Hits         1018     1021       +3     
+ Misses       1089     1082       -7     
- Partials      143      146       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tony tony force-pushed the tmuxp-load-exception-bug branch 2 times, most recently from 6c80021 to 3415a70 Compare December 14, 2025 11:13
why: Reproduce tmuxp issue #1002 where attach() raises exception if
session is killed while user is attached.
what:
- Add test that simulates session killed during attach-session
- Mark as xfail since attach() currently calls refresh() which fails
- Documents expected behavior: attach() should not raise if session gone
@tony tony force-pushed the tmuxp-load-exception-bug branch from 557784a to 70d1383 Compare December 14, 2025 11:18
tony added 2 commits December 14, 2025 05:18
…illed

why: attach-session is a blocking interactive command where session state
can change arbitrarily during attachment, including being killed entirely.
Calling refresh() after such a command is semantically incorrect.
what:
- Remove self.refresh() call from Session.attach()

Fixes: tmux-python/tmuxp#1002
why: The fix in the previous commit resolves the issue, so the test
should now pass and serve as a permanent regression guard.
what:
- Remove xfail marker from test_session_attach_does_not_fail_if_session_killed_during_attach
@tony tony changed the title fix(Session.attach): Remove refresh() call that fails after session killed fix(Session.attach()): Remove refresh() call that fails after session killed Dec 14, 2025
tony added a commit that referenced this pull request Dec 14, 2025
why: Document the bug fix and behavioral change for the upcoming release.
what:
- Add bug fix entry for #616 (attach no longer fails if session killed)
- Add breaking change note that attach() no longer calls refresh()
tony added a commit that referenced this pull request Dec 14, 2025
why: Document the bug fix and behavioral change for the upcoming release.
what:
- Add bug fix entry for #616 (attach no longer fails if session killed)
- Add breaking change note that attach() no longer calls refresh()
@tony tony force-pushed the tmuxp-load-exception-bug branch from 4af426b to 1c31e04 Compare December 14, 2025 11:23
tony added a commit that referenced this pull request Dec 14, 2025
why: Document the bug fix and behavioral change for the upcoming release.
what:
- Add bug fix entry for #616 (attach no longer fails if session killed)
- Add breaking change note that attach() no longer calls refresh()
@tony tony force-pushed the tmuxp-load-exception-bug branch from 1c31e04 to 1d47867 Compare December 14, 2025 11:26
why: Document the bug fix and behavioral change for the upcoming release.
what:
- Add breaking change note that attach() no longer calls refresh()
- Add bug fix entry for session killed during attachment
@tony tony force-pushed the tmuxp-load-exception-bug branch from 1d47867 to 9826825 Compare December 14, 2025 11:27
@tony
Copy link
Member Author

tony commented Dec 14, 2025

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

🤖 Generated with Claude Code

@tony tony merged commit 0c644b8 into master Dec 14, 2025
14 checks passed
@tony tony deleted the tmuxp-load-exception-bug branch December 14, 2025 11:51
tony added a commit to tmux-python/tmuxp that referenced this pull request Dec 14, 2025
## libtmux 0.52.1 -> 0.53.0

Bug fix for session attaching

## Bug fix for `tmuxp load`

### User Experience

After running `tmuxp load`, users would see this traceback printed to their terminal after detaching:

```
Traceback (most recent call last):
  File "/home/d/.local/bin/tmuxp", line 7, in <module>
    sys.exit(cli.cli())
  ...
  File ".../tmuxp/cli/load.py", line 152, in _load_attached
    builder.session.attach()
  File ".../libtmux/session.py", line 332, in attach
    self.refresh()
  File ".../libtmux/neo.py", line 242, in fetch_obj
    raise exc.TmuxObjectDoesNotExist(...)
libtmux.exc.TmuxObjectDoesNotExist: Could not find object
```

### Root Cause

The issue was caused by libtmux's `Session.attach()` calling `refresh()` after `attach-session` returned. Since `attach-session` is a **blocking interactive command**, the session state can change arbitrarily during attachment - including being killed entirely.

### Timeline

- **Feb 2024**: 9a5147aa - `Session.attach()` was added with the `refresh()` call
- **Nov 2025**: tmuxp fdafdd2b switched from `attach_session()` to `attach()`
- Users started experiencing the bug

### Fix

The fix is in libtmux: tmux-python/libtmux#616

This PR adds a regression test to tmuxp to ensure the behavior is documented and tested.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants