Skip to content

remote-tmux: let a failed socket request say what failed - #17134

Merged
teamleaderleo merged 3 commits into
manaflow-ai:mainfrom
ejc3:fix/remote-tmux-socket-error-text
Oct 3, 2026
Merged

teamleaderleo merged 3 commits into
manaflow-ai:mainfrom
ejc3:fix/remote-tmux-socket-error-text

Conversation

@ejc3

@ejc3 ejc3 commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Every remote tmux request that fails reports the same thing from the CLI, whatever went wrong:

$ cmux ssh-tmux build-box --new-window
Connecting to build-box…
Error: The Cloud VM request failed. Retry, or check the machine's status with `cmux vm ls`.

The host is an ssh host and no Cloud VM is involved. The real error in that run was "host unreachable: app not ready".

Remote tmux socket methods run through v2VmCall, the wrapper Cloud VM requests use. Its last fallback, cloudVMSafeErrorMessage, returns the Cloud VM line for any error it does not recognise, and RemoteTmuxError is not one it recognises. RemoteTmuxError.message is app-owned wording, and it already flattens and caps any remote text it includes, so the fallback now returns it as it is. The comment on RemoteTmuxError's CustomStringConvertible conformance says the socket path was meant to surface that message.

Testing

RemoteTmuxSocketErrorTextTests throws three RemoteTmuxError cases through v2VmCall and reads the message out of the encoded reply.

Run with xcodebuild test-without-building -scheme cmux-unit -only-testing:cmuxTests/RemoteTmuxSocketErrorTextTests:

  • fa61c07, the test alone: all three cases fail, each returning the Cloud VM line.
  • c9b0c25, with the fix: passes, along with RemoteTmuxMirrorCloseDetachTests, RemoteTmuxAuthTests and RemoteTmuxMissingTmuxTests (46 tests in 4 suites).

I also checked it from the CLI against a live tmux server on a local build that carries this change on top of other branches of mine. A failing cmux ssh-tmux printed the Cloud VM line before and its own reason after.

Changelog

Fixed: A failed cmux ssh-tmux now reports why it failed instead of a Cloud VM error.

Checklist

  • Behavior changes have added or updated tests, or Testing says why not

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Fixed failed remote tmux requests reporting the Cloud VM error line instead of their own reason.

Remote tmux socket methods run through v2VmCall, the wrapper Cloud VM requests use, and its fallback returns "The Cloud VM request failed" for any error it does not recognize. RemoteTmuxError was unrecognized, so a failing cmux ssh-tmux pointed users at cmux vm ls even when no Cloud VM was involved. The wrapper now returns RemoteTmuxError.message as-is, since it already flattens and caps any remote text it includes.

  • Added RemoteTmuxSocketErrorTextTests covering three RemoteTmuxError cases routed through v2VmCall.

Written for commit 30da6b1. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Remote tmux errors now display their specific message instead of being formatted as a Cloud VM error.

ejc3 added 2 commits October 3, 2026 00:03
…line

Remote tmux requests share a socket wrapper with Cloud VM requests. Its
fallback answers any error it does not recognise with "The Cloud VM request
failed", so every remote tmux failure reached the CLI as that.
The wrapper remote tmux requests share with Cloud VM requests answered any
error it did not recognise with the Cloud VM line. RemoteTmuxError carries
app-owned wording with remote text already flattened and capped, so it is
returned as it is.
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

🧰 Additional context used
📚 Code guidelines (2)
.github/review-bot-rules/source-control-artifacts.md — configured
.github/review-bot-rules/swiftpm-package-resolved.md — configured

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: c6c6447d-25b1-4841-8238-b39c2f468d0e
📥 Commits

Reviewing files that changed from the base of the PR and between c9b0c25 and 30da6b1.

📒 Files selected for processing (1)
  • cmux.xcodeproj/project.pbxproj

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 1 remain after this review.


📝 Walkthrough

Walkthrough

Error formatting now returns RemoteTmuxError.message directly. New tests check the JSON error message for three remote tmux failure cases.

Changes

Remote tmux error text

Layer / File(s) Summary
Format and test remote tmux errors
Sources/TerminalController.swift, cmuxTests/RemoteTmuxSocketErrorTextTests.swift, cmux.xcodeproj/project.pbxproj
TerminalController returns the message from RemoteTmuxError. Tests check that three failure cases produce their own message and exclude “Cloud VM,” ignoring case. The Xcode project includes the test file in the test target.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~8 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 30da6

Remote tmux failures retain their intended error messages, with no identified issue blocking the change from merging.

Architecture Summary

Architecture risk: 🔵 Low · up to 30da6

The change affects 3 systems.

Changed systems: cmux.xcodeproj, cmuxTests, Sources

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — cmux.xcodeproj (service) was modified; 1 changed file maps to changed impact.
  • observed — cmuxTests (service) was modified; 1 changed file maps to changed impact.
  • observed — Sources (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in Sources/TerminalController.swift: Adds a RemoteTmuxError case that returns its message directly; other errors continue to the existing handling.
  • observed — Modified behavior in cmuxTests/RemoteTmuxSocketErrorTextTests.swift: Adds Foundation and Testing imports and conditionally imports cmux_DEV or cmux for test access.
  • observed — Modified behavior in cmuxTests/RemoteTmuxSocketErrorTextTests.swift: Adds a parameterized test for unreachable, launch-failed, and window-creation failures. It extracts the reply’s JSON error message and expects it to equal failure.message and exclude “Cloud VM” case-insensitively.
  • observed — Modified behavior in cmux.xcodeproj/project.pbxproj: Adds the test file’s build-file entry for the Sources build phase.

Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux User-Facing Error Privacy ❌ Error The diff exposes raw remote command errors to cmux end users. RemoteTmuxError.commandFailed stores SSH/tmux stderr, and its message interpolates that stderr after only flattening control character… Change the production socket formatter so it does not return remote stderr or other unreviewed upstream text in user-facing errors. Use app-authored, safe error copy for RemoteTmuxError.commandFailed and related cases. Keep raw diagnostic…
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (23 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly describes the main change: remote tmux socket failures now report the reason for the failure.
Description check ✅ Passed The description includes the problem and resulting behavior, test coverage and results, a changelog entry, and the applicable behavior-test checklist item. It omits the demo video or screenshot reques…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Cloud Persistent Session And Early Input ✅ Passed The check does not apply to this diff. The only production change adds RemoteTmuxError.message handling in cloudVMSafeErrorMessage; the other changes add a focused error-text test and register it in t…
Cmux Swift Actor Isolation ✅ Passed The only production Swift change adds a RemoteTmuxError cast and reads its message in cloudVMSafeErrorMessage, an existing private nonisolated static formatter. RemoteTmuxError is an existin…
Cmux Swift Blocking Runtime ✅ Passed The production diff only adds a RemoteTmuxError type check and returns its message from the existing error formatter. It adds no blocking wait, sleep, delayed dispatch, polling, sync dispatch, or lo…
Cmux Browser Automation Off-Main ✅ Passed The pull request changes only error formatting for RemoteTmuxError and adds a test for that message. It does not change browser command routing, actor hops, or worker-lane behavior. The browser auto…
Cmux Expensive Synchronous Load ✅ Passed The production diff adds only a RemoteTmuxError type check and returns its message in cloudVMSafeErrorMessage. RemoteTmuxError.message sanitizes and caps error text; the change adds no agent-h…
Cmux Cache Substitution Correctness ✅ Passed The changed production code adds a RemoteTmuxError formatting branch in cloudVMSafeErrorMessage. v2VmCall uses that helper to encode an error reply. The patch does not replace an authoritative r…
Cmux No Hacky Sleeps ✅ Passed The diff changes only Swift source, a Swift test, and Xcode project configuration. It adds no production TypeScript, JavaScript, shell, or build/runtime script changes covered by this check. The added…
Cmux Algorithmic Complexity ✅ Passed The production diff adds one RemoteTmuxError type check and returns its message. That property sanitizes one error string in a single linear pass. The change adds no nested scans, repeated collect…
Cmux Swift Concurrency ✅ Passed The diff adds only a RemoteTmuxError message branch to error formatting and a test that invokes v2VmCall synchronously. It introduces no background Dispatch work, Combine state, completion-handler…
Cmux Swift @Concurrent ✅ Passed The changed implementation adds only a synchronous RemoteTmuxError formatting branch inside cloudVMSafeErrorMessage, which is nonisolated and synchronous. The added test calls the existing synch…
Cmux Swift Package Boundaries ✅ Passed The production diff adds only a RemoteTmuxError case to TerminalController.cloudVMSafeErrorMessage, the app's socket error-formatting wrapper. It returns the existing error's message; it does no…
Cmux Swiftpm Lockfiles ✅ Passed The PR changes only Sources/TerminalController.swift, cmux.xcodeproj/project.pbxproj, and a new test file. The project-file additions only register the test source; they do not change SwiftPM pack…
Cmux Swift Logging ✅ Passed The Swift diff adds no logging statements or diagnostic output. It returns RemoteTmuxError.message in the socket error response through v2VmCall; this is user-facing error text, not logging. The t…
Cmux Full Internationalization ✅ Passed The production diff only adds a branch that returns RemoteTmuxError.message; it adds no user-facing text or catalog changes. RemoteTmuxError.message already uses String(localized:defaultValue:) …
Cmux Swiftui State Layout ✅ Passed The pull request does not introduce SwiftUI state or layout changes. Its Swift changes add RemoteTmuxError message handling in TerminalController and add socket-error tests; no changed Swift lines mat…
Cmux Architecture Rethink ✅ Passed The PR adds only a RemoteTmuxError formatting branch and test registration. RemoteTmuxError.message owns user-facing wording and sanitizes remote details. The change adds no timing repair, mutable…
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The PR changes only error formatting in TerminalController.swift, Xcode test-target registration, and a new test fixture. The added implementation returns RemoteTmuxError.message; it does not add …
Cmux Source Artifacts ✅ Passed The three changed paths are Sources/TerminalController.swift, cmux.xcodeproj/project.pbxproj, and cmuxTests/RemoteTmuxSocketErrorTextTests.swift. The diff adds application source, registers a te…
Cmux No Test Or Debug Seam In Production Source ✅ Passed The production-source diff only adds a RemoteTmuxError case to cloudVMSafeErrorMessage and returns its existing message for request-error formatting. It adds no debug/test guard, test- or debug-…
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 1 files. (1 skipped: 1 unsupported.)

Full details: Cmux User-Facing Error Privacy

Explanation

The diff exposes raw remote command errors to cmux end users. RemoteTmuxError.commandFailed stores SSH/tmux stderr, and its message interpolates that stderr after only flattening control characters and capping length (Sources/RemoteTmuxError.swift:35-58). Failed SSH commands construct this case with result.stderr (Sources/RemoteTmuxSSHTransport.swift:58-63; Sources/RemoteTmuxSSHTransport+MissingTmux.swift:12-18). The changed branch returns RemoteTmuxError.message from the production socket error formatter (Sources/TerminalController.swift:4090-4094), and v2VmCall places it in the API error body (Sources/TerminalController.swift:4030-4035). The product CLI calls remote.tmux.mirror or remote.tmux.window (CLI/cmux.swift:12144-12151), decodes the error message (CLI/SocketClient+V2.swift:67-85), and prints it to stderr (CLI/cmux.swift:42908-42915). The new code therefore makes raw upstream stderr user-visible. Flattening and truncating do not redact raw messages, which the policy explicitly prohibits.

Resolution

Change the production socket formatter so it does not return remote stderr or other unreviewed upstream text in user-facing errors. Use app-authored, safe error copy for RemoteTmuxError.commandFailed and related cases. Keep raw diagnostics in sanitized internal logs or telemetry, not in the API error body or CLI output. Add a regression test that throws a RemoteTmuxError.commandFailed containing a recognizable upstream diagnostic and verifies that the socket reply does not include it.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 3, 2026 •

Copy link
Copy Markdown
Contributor

CI failure attribution

CI failed on 30da6b15ce (run 37155148040 attempt 2): 1 code, 1 unknown.

Job Verdict Why
Fast static checks code a static check failed
guards / workflow-guard-tests / ci unknown no known signature; failed step: Propagate failed independent fast guard
Matched log lines
Fast static checks: FAILED localization (1.27s)

Not re-run automatically: Fast static checks, guards / workflow-guard-tests / ci are not machine failures.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cursor

cursor Bot commented Oct 3, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

CI fast guards failed on 30da6b15ce (https://github.com/manaflow-ai/cmux/actions/runs/37155147931). It does not block the merge; a red guard merged into main breaks it for every open PR.

Validate macOS jobs select a pinned Xcode (red on main too, not this PR)

Main has failed this step since #17206 by @teamleaderleo (self-merged) (#17169). Merge main again once the fix lands there.

Validate owned Mac build state (red on main too, not this PR)

Main has failed this step since #17168 by @teamleaderleo (self-merged) (#17169). Merge main again once the fix lands there.

Validate fork runner routing (red on main too, not this PR)

Main has failed this step since #17206 by @teamleaderleo (self-merged) (#17169). Merge main again once the fix lands there.

Run canonical CMUX CI guard profile (red on main too, not this PR)

Main has failed this step since #17206 by @teamleaderleo (self-merged) (#17169). Merge main again once the fix lands there.

Agents: python3 scripts/ci/guard_attribution.py fix applies the mechanical fixes locally. This comment is updated in place on each push.

@teamleaderleo
teamleaderleo merged commit 46b5f9c into manaflow-ai:main Oct 3, 2026
60 of 67 checks passed
@teamleaderleo

Copy link
Copy Markdown
Collaborator

Merged, thank you @ejc3! :D

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Merge receipt for 30da6b15ce, merged 2026-10-03 21:42:06 UTC

  • Not verified at merge: ci-status (failure), CI fast guards (failure), Fast static checks (failure), guards (18) (failure), linux-preflight (failure), tests (failure)
  • Verified: backend migrations applied, CI timing, GhosttyKit release check, plan, Web complexity, web-validation
  • Skipped by policy: apply-production, apply-staging, browser, Claude wrapper regressions, Dogfood build #​${{ github.event.pull_request.number }}, full-suite-coverage, macos, macOS admission gate, remote-daemon, suite-coverage, ui-tests, web, and 3 more
  • Full suite: runs on main after merge.

Labeled merged-unverified: if main breaks near this merge, look here first.

@github-actions github-actions Bot added the merged-unverified A judging check was not green at merge; see the merge receipt comment label Oct 3, 2026
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

main no longer compiles after this merge

@teamleaderleo @ejc3: after 46b5f9c4ea landed on main, the app-host test product (the app and cmuxTests, build-for-testing) stops compiling. These errors first show up in a range of 4 merges (9c41d59d65..d8ef7e7fab), and this pull request's diff is the one that reaches them. The other merges in that range (984baea12f, e88d636d7b, d8ef7e7fab) are being compiled on their own to confirm.

Evidence: https://github.com/manaflow-ai/cmux/actions/runs/37156042656/job/111299626496

/tmp/cmux-ci-blacksmith-6vcpu-macos-15-Runner-cb61267037/src/cmuxTests/RightSidebarTabCustomizationTests.swift:126: error: cannot find 'RightSidebarModeBarDragLayout' in scope
/tmp/cmux-ci-blacksmith-6vcpu-macos-15-Runner-cb61267037/src/cmuxTests/RightSidebarTabCustomizationTests.swift:126: error: generic parameter 'T' could not be inferred
/tmp/cmux-ci-blacksmith-6vcpu-macos-15-Runner-cb61267037/src/cmuxTests/RightSidebarTabCustomizationTests.swift:144: error: type 'Any' cannot conform to 'Equatable' [#ProtocolTypeNonConformance]
/tmp/cmux-ci-blacksmith-6vcpu-macos-15-Runner-cb61267037/src/cmuxTests/RightSidebarTabCustomizationTests.swift:146: error: reference to member 'files' cannot be resolved without a contextual type
/tmp/cmux-ci-blacksmith-6vcpu-macos-15-Runner-cb61267037/src/cmuxTests/RightSidebarTabCustomizationTests.swift:146: error: reference to member 'sessions' cannot be resolved without a contextual type
/tmp/cmux-ci-blacksmith-6vcpu-macos-15-Runner-cb61267037/src/cmuxTests/RightSidebarTabCustomizationTests.swift:146: error: reference to member 'find' cannot be resolved without a contextual type
/tmp/cmux-ci-blacksmith-6vcpu-macos-15-Runner-cb61267037/src/cmuxTests/RightSidebarTabCustomizationTests.swift:146: error: reference to member 'machines' cannot be resolved without a contextual type

Nothing blocks merging meanwhile. A fix-forward (or, failing that, a revert) is attempted automatically unless an open pull request already fixes this.

main_compile_attribution.py: post-merge, nothing here gates a merge.

rustybret pushed a commit to rustybret/bmux that referenced this pull request Oct 3, 2026
00f182f Set Claude idle after reentrant stop without work (manaflow-ai#16635)
d8ef7e7 Reject unknown and valueless options in cmux hooks setup (manaflow-ai#17183)
46b5f9c remote-tmux: let a failed socket request say what failed (manaflow-ai#17134)
e88d636 remote-tmux: re-read a pane from tmux when its width changes, not only when it grows (manaflow-ai#17140)
984baea remote-tmux: close a window emptied by gathering its mirrors into a new one (manaflow-ai#17141)
9c41d59 fix: recover hidden terminal renderer after window attach (manaflow-ai#16548)
70854a5 ci: publish dogfood artifacts from red CI runs (manaflow-ai#17210)
db77e58 fix(cli): reject missing notify text values (manaflow-ai#16778)
76ccbfc ci: activate org-member dogfood artifact publisher (manaflow-ai#17206)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merged-unverified A judging check was not green at merge; see the merge receipt comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants