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

  1. Retry Get() with backoff until a non-'connecting...' error or a valid Connector is returned
  2. Wait for successful initialization (e.g. poll until err is nil) before using the connector
  3. 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

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.