henrygd/beszel · error
timeout
Error message
timeout
What it means
createSessionWithTimeout bounds SSH session creation with context.WithTimeout. If the goroutine dialing/opening the session does not produce a session or error before the deadline, ctx.Done() fires and the call returns the literal error 'timeout'. The underlying goroutine is abandoned (the session, if it later succeeds, leaks).
Source
Thrown at internal/hub/systems/system.go:790
sessionChan := make(chan *ssh.Session, 1)
errChan := make(chan error, 1)
go func() {
if session, err := client.NewSession(); err != nil {
errChan <- err
} else {
sessionChan <- session
}
}()
select {
case session := <-sessionChan:
return session, nil
case err := <-errChan:
return nil, err
case <-ctx.Done():
return nil, fmt.Errorf("timeout")
}
}
// closeSSHConnection closes the SSH connection but keeps the system in the manager
func (sys *System) closeSSHConnection() {
if sys.sshTransport != nil {
sys.sshTransport.Close()
}
if client := sys.client.Swap(nil); client != nil {
client.Close()
}
}
// closeWebSocketConnection closes the WebSocket connection but keeps the system in the manager
// to allow updating via SSH. It will be removed if the WS connection is re-established.
// The system will be set as down a few seconds later if the connection is not re-established.
func (sys *System) closeWebSocketConnection() {
if sys.WsConn != nil {View on GitHub (pinned to b38fb7dafa)
Solutions
- Verify network reachability/latency to the agent host (ping, ssh -v from the hub host)
- Increase the SSH session timeout configured in the hub settings
- Check the agent host's sshd is running and not throttling (MaxStartups) and that the firewall allows port 22
- Reduce concurrent SSH session creation storms; rely on the manager's reconnect logic
Example fix
// before session, err := sys.createSessionWithTimeout(5 * time.Second) // after session, err := sys.createSessionWithTimeout(30 * time.Second) // longer timeout for slow links
Defensive patterns
Strategy: retry
Validate before calling
conn, err := net.DialTimeout("tcp", host+":22", 5*time.Second)
if err != nil {
return fmt.Errorf("agent host unreachable before SSH attempt: %w", err)
} Try / catch
session, err := sys.createSessionWithTimeout(timeout)
if err != nil && err.Error() == "timeout" {
// backoff then retry once
time.Sleep(2 * time.Second)
session, err = sys.createSessionWithTimeout(timeout * 2)
}
return err Prevention
- Configure a timeout generous enough for WAN links to agent hosts
- Monitor hub-agent latency and alert on degradation
- Ensure sshd on agents is reachable and not throttling (MaxStartups)
- Avoid firewalls that silently drop packets causing hang-until-timeout
When it happens
Trigger: The ssh.Dial / client.NewSession call in the spawned goroutine exceeds the configured timeout — slow network to the agent host, SSH server not responding, DNS stalls, or an unreachable host where TCP connect hangs past the deadline.
Common situations: Firewall dropping packets silently (no RST) so the TCP handshake hangs; heavily loaded agent host; SSH server MaxStartups throttling new connections; transient network partition between hub and agent.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- timeout creating session
- temperature collection timed out
- SSH disabled
- no websocket connection
- ${resp.Error}
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/42581e0bda9feddc.
Report an issue: GitHub.