charmbracelet/crush · error

failed to get session: %w

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.

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)

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.