bcicen/ctop · info
connecting...
Error message
connecting...
What it means
ConnectorSuper is asynchronous: NewConnectorSuper immediately sets its internal err to a 'connecting...' placeholder and starts a background loop that establishes the real connection. Any early Get() call before the first successful connection returns this transient error, not a real failure.
Source
Thrown at connector/main.go:41
// Get returns a single container.Container by ID
Get(string) (*container.Container, bool)
// Wait blocks until the underlying connection is lost
Wait() struct{}
}
// ConnectorSuper provides initial connection and retry on failure for
// an undlerying Connector type
type ConnectorSuper struct {
conn Connector
connFn ConnectorFn
err error
lock sync.RWMutex
}
func NewConnectorSuper(connFn ConnectorFn) *ConnectorSuper {
cs := &ConnectorSuper{
connFn: connFn,
err: fmt.Errorf("connecting..."),
}
go cs.loop()
return cs
}
// Get returns the underlying Connector, or nil and an error
// if the Connector is not yet initialized or is disconnected.
func (cs *ConnectorSuper) Get() (Connector, error) {
cs.lock.RLock()
defer cs.lock.RUnlock()
if cs.err != nil {
return nil, cs.err
}
return cs.conn, nil
}
func (cs *ConnectorSuper) setError(err error) {
cs.lock.Lock()View on GitHub (pinned to 59f00dd6aa)
Solutions
- Retry Get() with backoff until a non-'connecting...' error or a valid Connector is returned
- Wait for successful initialization (e.g. poll until err is nil) before using the connector
- Treat this as transient state and gate dependent code on connector readiness
Example fix
// before
cs, _ := connector.ByName("docker")
conn, err := cs.Get() // 'connecting...'
// after
for {
conn, err := cs.Get()
if err == nil || err.Error() != "connecting..." { break }
time.Sleep(100 * time.Millisecond)
} Defensive patterns
Strategy: retry
Validate before calling
cs, _ := connector.ByName(name)
// readiness probe: loop until Get() stops returning the placeholder error
for cs.Get() != nil && cs.Get().Error() == "connecting..." { time.Sleep(100*time.Millisecond) } Type guard
func ready(cs *connector.ConnectorSuper) bool { err := func() error { _, e := cs.Get(); return e }(); return err == nil } Try / catch
conn, err := cs.Get()
if err != nil && err.Error() == "connecting..." {
time.Sleep(100 * time.Millisecond) // retry
} Prevention
- Never use the connector immediately after ByName; wait for readiness
- Add a startup readiness gate with timeout
- Log initialization state for debugging
When it happens
Trigger: Calling Get() on a ConnectorSuper right after ByName(), before the background loop has completed the first successful connection.
Common situations: Application startup reading from connectors immediately at init; no wait/backoff before first use; fast-failing checks in health probes during boot.
Related errors
AI-assisted analysis of bcicen/ctop@59f00dd6aa (2026-09-02).
Data as JSON: /api/errors/688e52153a987eb6.
Report an issue: GitHub.