{"record":{"id":"2d771d569ddd1cd4","repo":"charmbracelet/crush","slug":"failed-to-get-session-w-2d771d","errorCode":null,"errorMessage":"failed to get session: %w","messagePattern":"failed to get session: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":611,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get messages: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"failed to get messages: status code %d\", rsp.StatusCode)\n\t}\n\tvar msgs []proto.Message\n\tif err := json.NewDecoder(rsp.Body).Decode(&msgs); err != nil && !errors.Is(err, io.EOF) {\n\t\treturn nil, fmt.Errorf(\"failed to decode messages: %w\", err)\n\t}\n\treturn msgs, nil\n}\n\n// GetSession retrieves a specific session as a proto type.\nfunc (c *Client) GetSession(ctx context.Context, id string, sessionID string) (*proto.Session, error) {\n\trsp, err := c.get(ctx, fmt.Sprintf(\"/workspaces/%s/sessions/%s\", id, sessionID), nil, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get session: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"failed to get session: status code %d\", rsp.StatusCode)\n\t}\n\tvar sess proto.Session\n\tif err := json.NewDecoder(rsp.Body).Decode(&sess); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode session: %w\", err)\n\t}\n\treturn &sess, nil\n}\n\n// ListSessionHistoryFiles retrieves history files for a session as proto types.\nfunc (c *Client) ListSessionHistoryFiles(ctx context.Context, id string, sessionID string) ([]proto.File, error) {\n\trsp, err := c.get(ctx, fmt.Sprintf(\"/workspaces/%s/sessions/%s/history\", id, sessionID), nil, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get session history files: %w\", err)\n\t}","sourceCodeStart":593,"sourceCodeEnd":629,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L593-L629","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the wrapped cause: connection refused → start the server; deadline exceeded → increase timeout.","Verify the server address and that the crush server process is running.","Retry with a fresh context for transient network issues.","Fix proxy/VPN settings if the environment blocks the connection."],"exampleFix":"// before\nsess, err := client.GetSession(ctx, wsID, sessionID)\nif err != nil {\n    return err\n}\n// after: wait for server availability before resolving\nif err := waitForServer(ctx, client); err != nil {\n    return fmt.Errorf(\"cannot reach server to resolve session: %w\", err)\n}\nsess, err := client.GetSession(ctx, wsID, sessionID)","handlingStrategy":"retry","validationCode":"// Confirm the server answers before resolving sessions\nctxPing, cancel := context.WithTimeout(ctx, 3*time.Second)\ndefer cancel()\nif _, err := client.ListSessions(ctxPing, wsID); err != nil {\n    return fmt.Errorf(\"skipping session resolution: server unreachable: %w\", err)\n}","typeGuard":"func isDialFailure(err error) bool {\n    return strings.Contains(err.Error(), \"connection refused\") ||\n        strings.Contains(err.Error(), \"no such host\") ||\n        strings.Contains(err.Error(), \"i/o timeout\")\n}","tryCatchPattern":"sess, err := client.GetSession(ctx, wsID, sessionID)\nif err != nil && isDialFailure(err) {\n    if serr := waitForServer(ctx, client); serr == nil {\n        sess, err = client.GetSession(ctx, wsID, sessionID)\n    }\n}\nif err != nil {\n    return nil, err\n}","preventionTips":["Wait for server readiness once at startup instead of failing per-call","Use timeouts on all session-resolution calls to avoid hangs","Validate the configured server host/port before the first request","Retry dial failures with backoff; do not retry context.Canceled"],"tags":["network","http-client","session","connection"],"backgroundTag":"http-request-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}