You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(error): replace the opaque I/O error with actionable diagnostics #284
20 of the 48 genuine failures in the 2026-08-26 measurement surface as nothing more than Error: I/O error. The same string covers connection refusal, host key rejection, authentication failure and mid-session channel errors, so it distinguishes none of them.
Reproduced with no listener on the port, where OpenSSH says Connection refused:
X Error: I/O error
This cost real time during the measurement itself. Establishing that a cluster of failures was host key file selection rather than transport required attaching a live sshd and reading the server's log, because the client would not say which layer had failed. That is the cost every user of bssh pays on every failure.
Scope
Replace the blanket I/O error with errors that name the layer and the cause: DNS resolution, TCP connect (carrying the OS error), protocol or version negotiation, host key verification, authentication (naming the methods tried and refused), channel open, and command execution.
Carry the underlying std::io::Error kind and the OS errno through instead of collapsing them at the boundary. The refused-connection case must read as refused.
Match OpenSSH's wording where a script might reasonably match on it, and keep bssh-specific detail on additional lines rather than replacing the recognizable first line.
Report authentication failures with the method list, the way ssh does, since "no supported methods remain" and "the key was rejected" are different problems.
Preserve the exit status contract while doing this: connection and authentication failures exit 255, and a remote command's own status passes through unchanged.
Acceptance criteria
Connection refused, host unreachable, DNS failure, host key mismatch, and authentication exhaustion each produce a distinct message naming the cause.
The OS error is included where one exists.
No code path reports a bare I/O error, enforced by a test over the error enum.
Exit status 255 for client-side failures, and the remote status otherwise, covered by tests.
Activity
fix(auth): type authentication exhaustion failures