Skip to content

fix(tmux): don't resolve an empty pane ID to an unrelated mission - #33

Open
swade1987 wants to merge 2 commits into
mieubrisse:mainfrom
swade1987:fix/tmux-resolve-mission-empty-pane
Open

fix(tmux): don't resolve an empty pane ID to an unrelated mission#33
swade1987 wants to merge 2 commits into
mieubrisse:mainfrom
swade1987:fix/tmux-resolve-mission-empty-pane

Conversation

@swade1987

@swade1987 swade1987 commented Aug 16, 2026

Copy link
Copy Markdown

(This post authored by my AgenC)

Bug

agenc tmux resolve-mission was printing a real (but unrelated) mission UUID for pane IDs that should have resolved to nothing, in two related cases:

  1. A genuinely empty pane ID (resolve-mission "").
  2. A pane ID containing #, such as an accidentally-unexpanded tmux format placeholder passed in literally — e.g. resolve-mission "#{pane_id}" (this is what actually surfaced the bug for me, while building a tmux status-bar popup — see [Feature] tmux status-bar popup: mission ID + checkout directory for a window #32).

Root cause

Two distinct issues, same downstream symptom:

1. Empty pane ID falls through to the general mission list. handleListMissions only takes the pane-specific lookup path when tmux_pane is non-empty:

tmuxPane := r.URL.Query().Get("tmux_pane")
if tmuxPane != "" {
    mission, err := s.db.GetMissionByTmuxPane(tmuxPane)
    ...
}

An empty value falls through to the general mission-list endpoint instead. tmux resolve-mission then does fmt.Print(responses[0].ID) — printing whatever mission happens to be first in that unrelated list, rather than treating an empty pane ID as a lookup miss.

2. The pane ID isn't URL-escaped before being sent. The request URL is built via raw string concatenation: "/missions?tmux_pane="+paneID. A pane ID containing # has everything from # onward parsed as a URL fragment and silently dropped before the request is sent — confirmed directly with a standalone url.Parse of the exact string this command builds:

RawQuery: tmux_pane=
Fragment: {pane_id}

So the server receives an empty tmux_pane, hits issue #1's fallthrough, and this command prints an unrelated mission's ID again — the two bugs compound, and #2 is the more likely real-world trigger, since # is exactly what any accidentally-unexpanded tmux format placeholder looks like.

Fix

Two commits:

  • Early return in runTmuxResolveMission when the pane ID is empty, before any server/database call.
  • url.QueryEscape the pane ID before building the request URL, so a value containing # (or any other URL-special character) can no longer be silently truncated.

Verification

Built the binary from this branch and tested directly against a real local AgenC server/database:

$ agenc tmux resolve-mission ""
$                                      # nothing - fixed
$ agenc tmux resolve-mission "#{pane_id}"
$                                      # nothing - fixed (previously printed a real, unrelated mission UUID)
$ agenc tmux resolve-mission "%129"
61590b9a-bd96-4759-8654-fa3395dfa59a  # real pane still resolves correctly - no regression

Also ran go build ./... and go test ./cmd/... (both pass) from this branch.

`agenc tmux resolve-mission ""` was returning a real mission UUID instead
of printing nothing. The server's /missions handler only takes the
pane-specific lookup path when tmux_pane is non-empty; an empty value
falls through to the general mission-list endpoint, and this command
then printed responses[0].ID - whatever mission happened to be first in
that unrelated list - rather than treating it as a lookup miss.

Adds an early return for an empty pane ID, matching the command's
documented contract ("prints nothing if no active mission is
associated with the pane"). Verified: resolve-mission "" now prints
nothing, and a real pane ID still resolves correctly.

Signed-off-by: Steven Wade <steven@stevenwade.co.uk>
Uncovered while verifying the previous commit: the request URL was built
via raw string concatenation ("/missions?tmux_pane="+paneID) with no
escaping. A pane ID containing "#" - exactly what an accidentally
unexpanded tmux format placeholder like "#{pane_id}" looks like - has
everything from "#" onward parsed as a URL fragment and silently
dropped before the request is sent. The server then sees an empty
tmux_pane value and falls through to the same general-mission-list path
the previous commit fixed for a truly empty input, so this command
would print an unrelated mission's ID instead of nothing.

Confirmed with a standalone url.Parse of the exact string this command
builds: RawQuery ends up "tmux_pane=", Fragment ends up "{pane_id}".

Verified: resolve-mission "#{pane_id}" now prints nothing (previously
printed a real, unrelated mission UUID), a real pane ID still resolves
correctly, and the empty-string case from the previous commit is
unaffected.

Signed-off-by: Steven Wade <steven@stevenwade.co.uk>
@mieubrisse

Copy link
Copy Markdown
Owner

Oops that sounds like a bug; will get to this when I get my Claude chunking through issues

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