{"record":{"id":"e9021e25e59fa88f","repo":"henrygd/beszel","slug":"failed-to-decode-response-w","errorCode":null,"errorMessage":"failed to decode response: %w","messagePattern":"failed to decode response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/hub/transport/ssh.go","lineNumber":108,"sourceCode":"\tstdin, err := session.StdinPipe()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif err := session.Shell(); err != nil {\n\t\treturn err\n\t}\n\n\t// Send request\n\thubReq := common.HubRequest[any]{Action: action, Data: req}\n\tif err := cbor.NewEncoder(stdin).Encode(hubReq); err != nil {\n\t\treturn fmt.Errorf(\"failed to encode request: %w\", err)\n\t}\n\tstdin.Close()\n\n\t// Read response\n\tvar resp common.AgentResponse\n\tif err := cbor.NewDecoder(stdout).Decode(&resp); err != nil {\n\t\treturn fmt.Errorf(\"failed to decode response: %w\", err)\n\t}\n\n\tif resp.Error != \"\" {\n\t\treturn errors.New(resp.Error)\n\t}\n\n\tif err := session.Wait(); err != nil {\n\t\treturn err\n\t}\n\n\treturn UnmarshalResponse(resp, action, dest)\n}\n\n// IsConnected returns true if the SSH connection is active.\nfunc (t *SSHTransport) IsConnected() bool {\n\treturn t.client != nil\n}\n","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/henrygd/beszel/blob/b38fb7dafa60812cc22e6a84ce313e94f1ce0a32/internal/hub/transport/ssh.go#L90-L126","documentation":"In transport.SSH Request (internal/hub/transport/ssh.go:108), after sending the request the hub CBOR-decodes the agent's reply from stdout into common.AgentResponse; failure is wrapped as 'failed to decode response'. Typically the stream ended (EOF) or returned non-CBOR output because the agent died or sshd emitted text instead of protocol data.","triggerScenarios":"Agent process exits before replying (stdout EOF); agent prints plain text/errors to stdout (login banners, shell init scripts, missing binary) contaminating the CBOR stream; truncated response when the session is closed early.","commonSituations":"Remote ~/.bashrc or /etc/profile echoing text on non-interactive SSH sessions; agent binary missing/not executable so sshd returns an error message; agent OOM-killed mid-request; agent version too old to speak the expected protocol.","solutions":["Check the agent is installed, executable and running on the remote host (systemctl status beszel-agent)","Remove anything printing to stdout in remote shell init files (.bashrc/.profile) for the SSH user","Read the wrapped cause: io.EOF means the agent closed the stream; cbor errors mean corrupted/garbage output","Upgrade the agent to a version compatible with the hub (0.19+ for generic Data responses)"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"out, err := sshClient.Output(\"command -v beszel-agent || echo MISSING\")\nif strings.TrimSpace(out) == \"MISSING\" {\n    return errors.New(\"agent binary not installed on remote host\")\n}","typeGuard":null,"tryCatchPattern":"err := t.Request(ctx, action, req, dest)\nif err != nil && strings.Contains(err.Error(), \"failed to decode response\") {\n    if errors.Is(err, io.EOF) {\n        return retryAfterReconnect(ctx, action, req, dest) // agent died mid-request\n    }\n    return err // garbage output; inspect agent env\n}","preventionTips":["Keep agent shell init (.bashrc/.profile) free of stdout output","Verify the agent binary exists and runs on every managed host","Keep hub and agent versions compatible","Alert on agent process restarts/OOM kills"],"tags":["ssh","cbor","deserialization","agent"],"backgroundTag":"response-decode-failed","analyzedSha":"b38fb7dafa60812cc22e6a84ce313e94f1ce0a32","analyzedAt":"2026-08-31T15:10:10.149Z","schemaVersion":2},"datasetVersion":"2026-08-31T19:17:28.585Z"}