{"record":{"id":"bd8e92ab4d060783","repo":"charmbracelet/crush","slug":"failed-to-get-sessions-w","errorCode":null,"errorMessage":"failed to get sessions: %w","messagePattern":"failed to get sessions: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":662,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create session: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"failed to create 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// ListSessions lists all sessions in a workspace as proto types.\nfunc (c *Client) ListSessions(ctx context.Context, id string) ([]proto.Session, error) {\n\trsp, err := c.get(ctx, fmt.Sprintf(\"/workspaces/%s/sessions\", id), nil, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get sessions: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"failed to get sessions: status code %d\", rsp.StatusCode)\n\t}\n\tvar sessions []proto.Session\n\tif err := json.NewDecoder(rsp.Body).Decode(&sessions); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode sessions: %w\", err)\n\t}\n\treturn sessions, nil\n}\n\n// GrantPermission grants a permission on a workspace. The returned\n// bool reports whether this call resolved the pending request (true)\n// or found it already resolved by a previous caller (false). A false\n// value is not an error — it just means another subscriber resolved\n// the same request first.\nfunc (c *Client) GrantPermission(ctx context.Context, id string, req proto.PermissionGrant) (bool, error) {","sourceCodeStart":644,"sourceCodeEnd":680,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L644-L680","documentation":"ListSessions failed inside c.get before a response was available; the transport error is wrapped with this message. The GET to /workspaces/{id}/sessions never completed — connection failure, DNS error, TLS problem, or context cancellation.","triggerScenarios":"GET /workspaces/{id}/sessions fails at the transport layer: server unreachable, connection reset, ctx deadline exceeded, or invalid characters in the workspace ID.","commonSituations":"Wrong base URL or server down; offline/VPN drop; timeout on large workspaces; workspace ID with characters needing URL escaping.","solutions":["Inspect the wrapped error for the root cause.","Verify the server address and workspace ID.","Retry with backoff on transient errors.","Increase context timeout if listing large workspaces times out.","Check network/VPN/TLS configuration."],"exampleFix":"// before\nsessions, err := client.ListSessions(ctx, wsID)\nif err != nil { return err }\n// after\nsessions, err := client.ListSessions(ctx, wsID)\nif err != nil {\n    var netErr net.Error\n    if errors.As(err, &netErr) && netErr.Timeout() {\n        // retry with longer deadline/backoff\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"if wsID == \"\" { return errors.New(\"workspace id required\") }\nif err := ctx.Err(); err != nil { return err }","typeGuard":"func isListTransportError(err error) bool {\n    var netErr net.Error\n    return err != nil && errors.As(err, &netErr)\n}","tryCatchPattern":"sessions, err := client.ListSessions(ctx, wsID)\nif err != nil {\n    if isListTransportError(err) {\n        return retryWithBackoff(3, func() error {\n            sessions, err = client.ListSessions(ctx, wsID)\n            return err\n        })\n    }\n    return err\n}","preventionTips":["Verify server address and workspace ID.","Use adequate context timeouts for large workspaces.","URL-escape the workspace ID.","Retry transient network errors with backoff."],"tags":["http","network","client"],"backgroundTag":"http-request-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}