charmbracelet/crush · error

failed to get config: %w

Error message

failed to get config: %w

What it means

pickLoggedInProvider fetches the workspace configuration via client.GetConfig to enumerate logged-in providers for the interactive logout picker. If that RPC fails, the error is wrapped with this message. It is a wrapper around the transport or server-side failure of the config endpoint, preserving the cause with %w.

Source

Thrown at internal/cmd/logout.go:126

	ctx := getLogoutContext()

	if err := cmp.Or(
		c.RemoveConfigField(ctx, wsID, config.ScopeGlobal, "providers.copilot.api_key"),
		c.RemoveConfigField(ctx, wsID, config.ScopeGlobal, "providers.copilot.oauth"),
	); err != nil {
		return err
	}

	fmt.Println(logoutHeaderStyle.Render("Successfully logged out of GitHub Copilot."))
	return nil
}

func pickLoggedInProvider(c *client.Client, wsID string) (string, error) {
	ctx := getLogoutContext()

	cfg, err := c.GetConfig(ctx, wsID)
	if err != nil {
		return "", fmt.Errorf("failed to get config: %w", err)
	}

	type loggedInProvider struct {
		id   string
		name string
	}

	// Only OAuth-based providers support login/logout. Keep this list in sync
	// with the switch in RunE and the login command.
	oauthProviders := map[string]string{
		"hyper":   "Hyper",
		"copilot": "GitHub Copilot",
	}

	var loggedIn []loggedInProvider
	for id, name := range oauthProviders {
		if p, ok := cfg.Providers.Get(id); ok && p.OAuthToken != nil {
			loggedIn = append(loggedIn, loggedInProvider{id: id, name: name})

View on GitHub (pinned to 7944b8e522)

Solutions

  1. Unwrap the error to see the root cause (transport vs status).
  2. Ensure the crush server/daemon is running and you are authenticated (try a cheap command like `crush models`).
  3. Verify the workspace id is valid; re-login if credentials expired.
  4. Retry the logout command once the server is reachable.
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: confirm server reachable before logout flow
if _, err := c.ListWorkspaces(ctx); err != nil {
    return fmt.Errorf("cannot reach server for logout: %w", err)
}

Try / catch

provider, err := pickLoggedInProvider(c, wsID)
if err != nil {
    if strings.Contains(err.Error(), "failed to get config") {
        // surface the wrapped cause and prompt re-login
    }
    return err
}

Prevention

When it happens

Trigger: Calling the logout flow (anonymous caller path) when GetConfig fails: server unreachable, workspace id invalid, authentication rejected, or the context returned by getLogoutContext is already canceled/timed out.

Common situations: Daemon not running when invoking `crush logout`; expired auth token causing 401 on the config endpoint; stale workspace id after workspace deletion; network offline.

Related errors


AI-assisted analysis of charmbracelet/crush@7944b8e522 (2026-08-29). Data as JSON: /api/errors/5e5bafc0fe09294e. Report an issue: GitHub.