henrygd/beszel · error
client not initialized
Error message
client not initialized
What it means
createSessionWithTimeout in internal/hub/systems/system.go:767 loads the system's cached SSH client via sys.client.Load(); if the atomic pointer is nil it means the SSH connection has never been established or was already closed, so no session can be created. This is a lifecycle guard preventing a nil-pointer dereference on golang.org/x/crypto/ssh Client methods.
Source
Thrown at internal/hub/systems/system.go:767
}
conn, err := dialer.Dial(network, addr)
if err != nil {
return nil, err
}
sshConn, chans, reqs, err := ssh.NewClientConn(conn, addr, config)
if err != nil {
_ = conn.Close()
return nil, err
}
return ssh.NewClient(sshConn, chans, reqs), nil
}
// createSessionWithTimeout creates a new SSH session with a timeout to avoid hanging
// in case of network issues
func (sys *System) createSessionWithTimeout(timeout time.Duration) (*ssh.Session, error) {
client := sys.client.Load()
if client == nil {
return nil, fmt.Errorf("client not initialized")
}
ctx, cancel := context.WithTimeout(sys.ctx, timeout)
defer cancel()
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:View on GitHub (pinned to b38fb7dafa)
Solutions
- Ensure the system's SSH connection is established (connectToSSH / Initialize) before issuing SSH operations
- Check the system is not paused/stopped in the hub UI before triggering SSH actions
- Reconnect the system and retry once the client is initialized
- If the race persists, add a readiness guard/wait around runSSHOperation calls
Example fix
// before
if sys.IsPaused() == false {
data, err := sys.GetData(ctx) // may hit 'client not initialized'
}
// after
if sys.IsConnected() {
data, err := sys.GetData(ctx)
} else {
if err := sys.Connect(); err != nil { return err }
data, err := sys.GetData(ctx)
} Defensive patterns
Strategy: try-catch
Validate before calling
if sys.GetClient() == nil { // atomic client pointer
return errors.New("system SSH client not initialized; connect first")
} Type guard
func (sys *System) HasClient() bool {
return sys.client.Load() != nil
} Try / catch
session, err := sys.createSessionWithTimeout(timeout)
if err != nil {
if err.Error() == "client not initialized" {
if cerr := sys.Connect(); cerr != nil { return cerr }
session, err = sys.createSessionWithTimeout(timeout)
}
if err != nil { return err }
} Prevention
- Always connect the system (Initialize/connectToSSH) before issuing SSH operations
- Gate SSH operations on an IsConnected/HasClient check
- Treat paused/stopped systems as ineligible for SSH commands
- Watch for races between initialization and the first monitoring tick
When it happens
Trigger: createSessionWithTimeout (called via runSSHOperation and an anonymous wrapper) runs while sys.client holds nil — e.g. the system was paused/stopped and closeSSHConnection or connectToSSH disconnect set the client to nil, or the system is being initialized concurrently and an SSH operation races ahead of the first connect.
Common situations: Hub restarting/initializing systems from the database while monitoring timers fire before the SSH connection completes; an agent host that dropped its connection so the manager cleared the client; calling SSH-based operations (logs, container info) on a paused system.
Related errors
- SSH disabled
- ${resp.Error}
- timeout creating session
- no key provided: must set -key flag, KEY env var, or KEY_FIL
- failed to read key file: %w
AI-assisted analysis of henrygd/beszel@b38fb7dafa (2026-08-31).
Data as JSON: /api/errors/99a3205822ef9eb0.
Report an issue: GitHub.