Tencent/WeKnora · error

failed to start client: %w

Error message

failed to start client: %w

What it means

Connect wraps errors from c.client.Start(ctx) (the mark3labs client's SSE/HTTP connection establishment) with 'failed to start client'. This is where actual network problems surface: DNS failure, connection refused, TLS errors, or non-2xx handshake responses. OAuth-required conditions are intercepted first and returned unwrapped as oauth-required errors.

Source

Thrown at internal/mcp/client.go:345

		return zero, refreshErr
	}
	return operation()
}

// Connect establishes connection to the MCP service
func (c *mcpGoClient) Connect(ctx context.Context) error {
	if c.connected {
		return ErrAlreadyConnected
	}

	_, err := oauthCall(ctx, c, func() (struct{}, error) {
		return struct{}{}, c.client.Start(ctx)
	})
	if err != nil {
		if oerr := asOAuthRequired(err); oerr != nil {
			return oerr
		}
		return fmt.Errorf("failed to start client: %w", err)
	}
	c.connected = true
	if c.service.TransportType == types.MCPTransportStdio {
		logger.GetLogger(ctx).Infof("MCP stdio client connected: %s %v",
			c.service.StdioConfig.Command, c.service.StdioConfig.Args)
	} else {
		logger.GetLogger(ctx).Infof("MCP client connected to %s", *c.service.URL)
	}
	return nil
}

// Disconnect closes the connection
func (c *mcpGoClient) Disconnect() error {
	if !c.connected {
		return nil
	}

	// Close the client

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Verify the service URL is reachable from the runtime: curl the /sse or /mcp endpoint from inside the deployment
  2. Check DNS, egress firewall, and proxy settings for the environment
  3. Confirm the server actually serves the configured transport (SSE vs streamable) at that path
  4. Inspect the wrapped cause for TLS vs connection vs HTTP-status specifics; fix cert/proxy config accordingly
  5. Retry with backoff for transient network errors; OAuth-required responses are surfaced separately and need re-authorization

Example fix

// before
if err := c.Connect(ctx); err != nil { return err } // no retry
// after
err := retry.Do(func() error { return c.Connect(ctx) }, retry.Attempts(3), retry.Delay(time.Second),
    retry.RetryIf(func(err error) bool { return !errors.Is(err, ErrOAuthRequired) }))
Defensive patterns

Strategy: try-catch

Validate before calling

func endpointReachable(raw string, timeout time.Duration) error {
    c := &http.Client{Timeout: timeout}
    resp, err := c.Head(raw)
    if err != nil { return err }
    resp.Body.Close()
    return nil
} // run as a preflight/diagnostic, not a hard gate

Type guard

func isStartFailure(err error) bool {
    return err != nil && strings.Contains(err.Error(), "failed to start client")
}
func isOAuthRequiredStart(err error) bool { return asOAuthRequired(err) != nil }

Try / catch

if err := c.Connect(ctx); err != nil {
    if asOAuthRequired(err) != nil { return handleReauth(err) }
    if isStartFailure(err) {
        log.Warnf("MCP start failed: %v", errors.Unwrap(err))
        return retryWithBackoff(ctx, func() error { return c.Connect(ctx) })
    }
    return err
}

Prevention

When it happens

Trigger: Connect called on an mcpGoClient whose server URL is unreachable, DNS-unresolvable, refusing connections, presenting a bad TLS cert, or timing out (30s default or AdvancedConfig.Timeout). Not thrown when already connected (that returns ErrAlreadyConnected).

Common situations: MCP server down or wrong port; service URL points to an internal hostname not resolvable from the deployment; corporate proxy/TLS interception; firewall blocking egress; server returns 404 on the /sse or /mcp endpoint path.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/9219bd8818ea78db. Report an issue: GitHub.