henrygd/beszel · error

failed to decode response: %w

Error message

failed to decode response: %w

What it means

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.

Source

Thrown at internal/hub/transport/ssh.go:108

	stdin, err := session.StdinPipe()
	if err != nil {
		return err
	}
	if err := session.Shell(); err != nil {
		return err
	}

	// Send request
	hubReq := common.HubRequest[any]{Action: action, Data: req}
	if err := cbor.NewEncoder(stdin).Encode(hubReq); err != nil {
		return fmt.Errorf("failed to encode request: %w", err)
	}
	stdin.Close()

	// Read response
	var resp common.AgentResponse
	if err := cbor.NewDecoder(stdout).Decode(&resp); err != nil {
		return fmt.Errorf("failed to decode response: %w", err)
	}

	if resp.Error != "" {
		return errors.New(resp.Error)
	}

	if err := session.Wait(); err != nil {
		return err
	}

	return UnmarshalResponse(resp, action, dest)
}

// IsConnected returns true if the SSH connection is active.
func (t *SSHTransport) IsConnected() bool {
	return t.client != nil
}

View on GitHub (pinned to b38fb7dafa)

Solutions

  1. Check the agent is installed, executable and running on the remote host (systemctl status beszel-agent)
  2. Remove anything printing to stdout in remote shell init files (.bashrc/.profile) for the SSH user
  3. Read the wrapped cause: io.EOF means the agent closed the stream; cbor errors mean corrupted/garbage output
  4. Upgrade the agent to a version compatible with the hub (0.19+ for generic Data responses)
Defensive patterns

Strategy: retry

Validate before calling

out, err := sshClient.Output("command -v beszel-agent || echo MISSING")
if strings.TrimSpace(out) == "MISSING" {
    return errors.New("agent binary not installed on remote host")
}

Try / catch

err := t.Request(ctx, action, req, dest)
if err != nil && strings.Contains(err.Error(), "failed to decode response") {
    if errors.Is(err, io.EOF) {
        return retryAfterReconnect(ctx, action, req, dest) // agent died mid-request
    }
    return err // garbage output; inspect agent env
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31). Data as JSON: /api/errors/e9021e25e59fa88f. Report an issue: GitHub.