{"record":{"id":"688e52153a987eb6","repo":"bcicen/ctop","slug":"connecting","errorCode":null,"errorMessage":"connecting...","messagePattern":"connecting\\.\\.\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"info","filePath":"connector/main.go","lineNumber":41,"sourceCode":"\t// Get returns a single container.Container by ID\n\tGet(string) (*container.Container, bool)\n\t// Wait blocks until the underlying connection is lost\n\tWait() struct{}\n}\n\n// ConnectorSuper provides initial connection and retry on failure for\n// an undlerying Connector type\ntype ConnectorSuper struct {\n\tconn   Connector\n\tconnFn ConnectorFn\n\terr    error\n\tlock   sync.RWMutex\n}\n\nfunc NewConnectorSuper(connFn ConnectorFn) *ConnectorSuper {\n\tcs := &ConnectorSuper{\n\t\tconnFn: connFn,\n\t\terr:    fmt.Errorf(\"connecting...\"),\n\t}\n\tgo cs.loop()\n\treturn cs\n}\n\n// Get returns the underlying Connector, or nil and an error\n// if the Connector is not yet initialized or is disconnected.\nfunc (cs *ConnectorSuper) Get() (Connector, error) {\n\tcs.lock.RLock()\n\tdefer cs.lock.RUnlock()\n\tif cs.err != nil {\n\t\treturn nil, cs.err\n\t}\n\treturn cs.conn, nil\n}\n\nfunc (cs *ConnectorSuper) setError(err error) {\n\tcs.lock.Lock()","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/bcicen/ctop/blob/59f00dd6aaebf48f3bc501e174f75f815c2619f0/connector/main.go#L23-L59","documentation":"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.","triggerScenarios":"Calling Get() on a ConnectorSuper right after ByName(), before the background loop has completed the first successful connection.","commonSituations":"Application startup reading from connectors immediately at init; no wait/backoff before first use; fast-failing checks in health probes during boot.","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"],"exampleFix":"// before\ncs, _ := connector.ByName(\"docker\")\nconn, err := cs.Get() // 'connecting...'\n// after\nfor {\n  conn, err := cs.Get()\n  if err == nil || err.Error() != \"connecting...\" { break }\n  time.Sleep(100 * time.Millisecond)\n}","handlingStrategy":"retry","validationCode":"cs, _ := connector.ByName(name)\n// readiness probe: loop until Get() stops returning the placeholder error\nfor cs.Get() != nil && cs.Get().Error() == \"connecting...\" { time.Sleep(100*time.Millisecond) }","typeGuard":"func ready(cs *connector.ConnectorSuper) bool { err := func() error { _, e := cs.Get(); return e }(); return err == nil }","tryCatchPattern":"conn, err := cs.Get()\nif err != nil && err.Error() == \"connecting...\" {\n    time.Sleep(100 * time.Millisecond) // retry\n}","preventionTips":["Never use the connector immediately after ByName; wait for readiness","Add a startup readiness gate with timeout","Log initialization state for debugging"],"tags":["async","initialization","transient"],"backgroundTag":"still-connecting","analyzedSha":"59f00dd6aaebf48f3bc501e174f75f815c2619f0","analyzedAt":"2026-09-02T23:34:03.832Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}