wavetermdev/waveterm · warning

context timeout

Error message

context timeout

What it means

WaitForConnect polls DeriveConnStatus every 100ms and returns this error when the caller-supplied context is canceled or its deadline expires while the connection is still in Status_Connecting. It signals 'gave up waiting' — the connection may still complete later, but this waiter stopped waiting.

Solutions

  1. Increase the context deadline passed to WaitForConnect (WSL cold start can take many seconds)
  2. Check final connection state after the timeout — the connection may have succeeded after you stopped waiting
  3. If cancellation was intentional, treat this as a normal cancellation and clean up rather than retrying
  4. Retry with a fresh context if the connect should be given another chance

Example fix

// before
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
// after
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
err := conn.WaitForConnect(ctx)
Defensive patterns

Strategy: try-catch

Try / catch

ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := conn.WaitForConnect(ctx); err != nil {
    if err.Error() == "context timeout" {
        // check final state: connection may have completed after we gave up
        if conn.DeriveConnStatus().Status == Status_Connected {
            err = nil
        }
    }
}

Prevention

When it happens

Trigger: Calling WaitForConnect with a context whose deadline is shorter than the time the WSL connection takes to establish, or canceling the context (user cancel / shutdown) mid-connect.

Common situations: Short timeouts (e.g. a few seconds) on slow machine or cold WSL startup; user cancels a connecting block; app shutdown cancels contexts while connections are still in progress.

Understand the failure class

Related errors


AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01). Data as JSON: /api/errors/bf7a2674994574f1. Report an issue: GitHub.

Appendix: source

Thrown at pkg/wslconn/wslconn.go:475

func (conn *WslConn) Reconnect(ctx context.Context) error {
	err := conn.Close()
	if err != nil {
		return err
	}
	return conn.Connect(ctx)
}

func (conn *WslConn) WaitForConnect(ctx context.Context) error {
	for {
		status := conn.DeriveConnStatus()
		if status.Status == Status_Connected {
			return nil
		}
		if status.Status == Status_Connecting {
			select {
			case <-ctx.Done():
				return fmt.Errorf("context timeout")
			case <-time.After(100 * time.Millisecond):
				continue
			}
		}
		if status.Status == Status_Init || status.Status == Status_Disconnected {
			return fmt.Errorf("disconnected")
		}
		if status.Status == Status_Error {
			return fmt.Errorf("error: %v", status.Error)
		}
		return fmt.Errorf("unknown status: %q", status.Status)
	}
}

// does not return an error since that error is stored inside of WslConn
func (conn *WslConn) Connect(ctx context.Context) error {
	var connectAllowed bool
	conn.WithLock(func() {

View on GitHub (pinned to a4447c1563)