charmbracelet/crush · error

failed to get session

Error message

failed to get session: %w

What it means

Thrown by Client.GetSession in internal/client/proto.go when the HTTP GET to /workspaces/{id}/sessions/{sessionID} fails at the transport layer, before any HTTP response. The wrapped c.get error (dial failure, timeout, canceled context) is returned. Called by resolveSession and resolveSessionByID.

Solutions

  1. Check the wrapped cause: connection refused → start the server; deadline exceeded → increase timeout.
  2. Verify the server address and that the crush server process is running.
  3. Retry with a fresh context for transient network issues.
  4. Fix proxy/VPN settings if the environment blocks the connection.

Example fix

// before
sess, err := client.GetSession(ctx, wsID, sessionID)
if err != nil {
    return err
}
// after: wait for server availability before resolving
if err := waitForServer(ctx, client); err != nil {
    return fmt.Errorf("cannot reach server to resolve session: %w", err)
}
sess, err := client.GetSession(ctx, wsID, sessionID)
Defensive patterns

Strategy: retry

Validate before calling

// Confirm the server answers before resolving sessions
ctxPing, cancel := context.WithTimeout(ctx, 3*time.Second)
defer cancel()
if _, err := client.ListSessions(ctxPing, wsID); err != nil {
    return fmt.Errorf("skipping session resolution: server unreachable: %w", err)
}

Type guard

func isDialFailure(err error) bool {
    return strings.Contains(err.Error(), "connection refused") ||
        strings.Contains(err.Error(), "no such host") ||
        strings.Contains(err.Error(), "i/o timeout")
}

Try / catch

sess, err := client.GetSession(ctx, wsID, sessionID)
if err != nil && isDialFailure(err) {
    if serr := waitForServer(ctx, client); serr == nil {
        sess, err = client.GetSession(ctx, wsID, sessionID)
    }
}
if err != nil {
    return nil, err
}

Prevention

When it happens

Trigger: Calling GetSession/resolveSession/resolveSessionByID while the server is unreachable, DNS fails, the context deadline expires, the connection is refused, or the network drops mid-request.

Common situations: Server down when resuming work; wrong server address in client config; sandboxed/containerized environment without network access to the server; corporate proxy blocking the connection; context canceled by an upstream timeout.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at internal/client/proto.go:611

	if err != nil {
		return nil, fmt.Errorf("failed to get messages: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to get messages: status code %d", rsp.StatusCode)
	}
	var msgs []proto.Message
	if err := json.NewDecoder(rsp.Body).Decode(&msgs); err != nil && !errors.Is(err, io.EOF) {
		return nil, fmt.Errorf("failed to decode messages: %w", err)
	}
	return msgs, nil
}

// GetSession retrieves a specific session as a proto type.
func (c *Client) GetSession(ctx context.Context, id string, sessionID string) (*proto.Session, error) {
	rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/sessions/%s", id, sessionID), nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get session: %w", err)
	}
	defer rsp.Body.Close()
	if rsp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("failed to get session: status code %d", rsp.StatusCode)
	}
	var sess proto.Session
	if err := json.NewDecoder(rsp.Body).Decode(&sess); err != nil {
		return nil, fmt.Errorf("failed to decode session: %w", err)
	}
	return &sess, nil
}

// ListSessionHistoryFiles retrieves history files for a session as proto types.
func (c *Client) ListSessionHistoryFiles(ctx context.Context, id string, sessionID string) ([]proto.File, error) {
	rsp, err := c.get(ctx, fmt.Sprintf("/workspaces/%s/sessions/%s/history", id, sessionID), nil, nil)
	if err != nil {
		return nil, fmt.Errorf("failed to get session history files: %w", err)
	}

View on GitHub (pinned to 7944b8e522)