{"record":{"id":"fc2fbfe0c787cee5","repo":"charmbracelet/crush","slug":"failed-to-get-session-history-files-w","errorCode":null,"errorMessage":"failed to get session history files: %w","messagePattern":"failed to get session history files: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":628,"sourceCode":"\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}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"failed to get session history files: status code %d\", rsp.StatusCode)\n\t}\n\tvar files []proto.File\n\tif err := json.NewDecoder(rsp.Body).Decode(&files); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode session history files: %w\", err)\n\t}\n\treturn files, nil\n}\n\n// CreateSession creates a new session in a workspace as a proto type.\nfunc (c *Client) CreateSession(ctx context.Context, id string, title string) (*proto.Session, error) {\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/sessions\", id), nil, jsonBody(proto.Session{Title: title}), http.Header{\"Content-Type\": []string{\"application/json\"}})\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create session: %w\", err)\n\t}","sourceCodeStart":610,"sourceCodeEnd":646,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L610-L646","documentation":"ListSessionHistoryFiles failed inside c.get, the low-level HTTP helper, before any response was available. The client wraps the transport-level error with this message. This fires when the request could not be completed at all: DNS failure, connection refused/reset, TLS error, context cancellation, or request-construction failure.","triggerScenarios":"GET /workspaces/{id}/sessions/{sessionID}/history fails at the transport layer: server unreachable, connection dropped mid-request, ctx cancelled/deadline exceeded, or invalid URL characters in id/sessionID causing request creation failure.","commonSituations":"Server not running or wrong base URL; network outage or VPN drop; context timeout on slow history endpoints; workspace or session IDs containing characters needing escaping.","solutions":["Inspect the wrapped error for the root cause (connection refused, no such host, context deadline exceeded).","Verify the server address/base URL and that the workspace ID and session ID are correct.","Retry with backoff if the error is transient (connection reset, timeout).","Check network connectivity, VPN, and TLS configuration.","URL-escape ids: ensure they contain no raw slashes or invalid characters."],"exampleFix":"// before\nfiles, err := client.ListSessionHistoryFiles(ctx, wsID, sessID)\nif err != nil { return err }\n// after\nfiles, err := client.ListSessionHistoryFiles(ctx, wsID, sessID)\nif err != nil {\n    var netErr net.Error\n    if errors.As(err, &netErr) && netErr.Timeout() {\n        // retry with backoff\n    }\n    return err\n}","handlingStrategy":"retry","validationCode":"// Pre-flight: ensure the server is reachable\nreq, _ := http.NewRequestWithContext(ctx, http.MethodGet, baseURL+\"/health\", nil)\nif _, err := http.DefaultClient.Do(req); err != nil {\n    return fmt.Errorf(\"server unreachable: %w\", err)\n}","typeGuard":"func isTransportError(err error) bool {\n    var netErr net.Error\n    return err != nil && errors.As(err, &netErr)\n}","tryCatchPattern":"files, err := client.ListSessionHistoryFiles(ctx, wsID, sessID)\nif err != nil {\n    if isTransportError(err) {\n        // retry with exponential backoff\n    }\n    return err\n}","preventionTips":["Verify the base URL and that the server is running.","Pass contexts with realistic deadlines.","URL-escape workspace and session IDs.","Add retry-with-backoff for transient network errors."],"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"}