{"record":{"id":"24ab354ee7fea1b3","repo":"wavetermdev/waveterm","slug":"cannot-connect-to-q-when-status-is-q-24ab35","errorCode":null,"errorMessage":"cannot connect to %q when status is %q","messagePattern":"cannot connect to %q when status is %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/wslconn/wslconn.go","lineNumber":505,"sourceCode":"\t}\n}\n\n// does not return an error since that error is stored inside of WslConn\nfunc (conn *WslConn) Connect(ctx context.Context) error {\n\tvar connectAllowed bool\n\tconn.WithLock(func() {\n\t\tif conn.Status == Status_Connecting || conn.Status == Status_Connected {\n\t\t\tconnectAllowed = false\n\t\t} else {\n\t\t\tconn.Status = Status_Connecting\n\t\t\tconn.Error = \"\"\n\t\t\tconnectAllowed = true\n\t\t}\n\t})\n\tlog.Printf(\"Connect %s\\n\", conn.GetName())\n\tif !connectAllowed {\n\t\tconn.Infof(ctx, \"cannot connect to %q when status is %q\\n\", conn.GetName(), conn.GetStatus())\n\t\treturn fmt.Errorf(\"cannot connect to %q when status is %q\", conn.GetName(), conn.GetStatus())\n\t}\n\tconn.FireConnChangeEvent()\n\terr := conn.connectInternal(ctx)\n\tconn.WithLock(func() {\n\t\tif err != nil {\n\t\t\tconn.Infof(ctx, \"ERROR %v\\n\\n\", err)\n\t\t\tconn.Status = Status_Error\n\t\t\tconn.Error = err.Error()\n\t\t\tconn.close_nolock()\n\t\t\ttelemetry.GoUpdateActivityWrap(wshrpc.ActivityUpdate{\n\t\t\t\tConn: map[string]int{\"wsl:connecterror\": 1},\n\t\t\t}, \"wsl-connconnect\")\n\t\t\ttelemetry.GoRecordTEventWrap(&telemetrydata.TEvent{\n\t\t\t\tEvent: \"conn:connecterror\",\n\t\t\t\tProps: telemetrydata.TEventProps{\n\t\t\t\t\tConnType: \"wsl\",\n\t\t\t\t},\n\t\t\t})","sourceCodeStart":487,"sourceCodeEnd":523,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wslconn/wslconn.go#L487-L523","documentation":"Connect() refuses to start a connection when the WSLConn's current status is already 'connecting' or 'connected' (the connectAllowed guard around line 494). Returning this error instead of double-connecting protects the connection state machine from concurrent connects.","triggerScenarios":"Calling Connect() (directly or via Reconnect()) while conn.GetStatus() is Status_Connecting or Status_Connected — e.g. two callers racing to connect the same connection, or Reconnect() invoked while a prior connect is still in flight.","commonSituations":"Frontend fires a reconnect action while the initial auto-connect is still running; a block-level 'ensure connected' call races with a user-triggered connect; stale UI shows 'disconnected' while the connection actually re-established.","solutions":["Check conn status (DeriveConnStatus()) before calling Connect and skip if already connecting/connected","Serialize connects through one code path (e.g. EnsureConnection) instead of calling Connect directly","Wait for the in-flight connect to settle (WaitForConnect) before issuing another Connect","If the connection appears connected but is actually dead, call Disconnect/Close first, then Connect"],"exampleFix":"// before\nerr := wslconn.Reconnect(ctx, connName)\n// after\nstatus := wslconn.DeriveConnStatusFor(connName)\nif status.Status == wslconn.Status_Connected || status.Status == wslconn.Status_Connecting {\n    return nil // already connected/connecting\n}\nerr := wslconn.Reconnect(ctx, connName)","handlingStrategy":"validation","validationCode":"st := wslconn.DeriveConnStatusFor(connName)\nif st != nil && (st.Status == wslconn.Status_Connecting || st.Status == wslconn.Status_Connected) {\n    return nil // nothing to do\n}\nerr := wslconn.Reconnect(ctx, connName)","typeGuard":null,"tryCatchPattern":"if err := conn.Connect(ctx); err != nil {\n    if strings.Contains(err.Error(), \"when status is\") {\n        // already connecting/connected; wait instead of retry\n        return conn.WaitForConnect(ctx)\n    }\n    return err\n}","preventionTips":["Route all connect requests through EnsureConnection instead of raw Connect","Debounce UI reconnect buttons","Track in-flight connect promises per connection","Check DeriveConnStatus before connecting"],"tags":["go","connection-state","concurrency","wsl"],"backgroundTag":"connection-already-open","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}