{"record":{"id":"6b045104cf934fbe","repo":"charmbracelet/crush","slug":"failed-to-summarize-session-w","errorCode":null,"errorMessage":"failed to summarize session: %w","messagePattern":"failed to summarize session: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":567,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get session agent info: %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 agent info: status code %d\", rsp.StatusCode)\n\t}\n\tvar info proto.AgentSession\n\tif err := json.NewDecoder(rsp.Body).Decode(&info); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode session agent info: %w\", err)\n\t}\n\treturn &info, nil\n}\n\n// AgentSummarizeSession requests a session summarization.\nfunc (c *Client) AgentSummarizeSession(ctx context.Context, id string, sessionID string) error {\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/agent/sessions/%s/summarize\", id, sessionID), nil, nil, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to summarize session: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"failed to summarize session: status code %d\", rsp.StatusCode)\n\t}\n\treturn nil\n}\n\n// InitiateAgentProcessing triggers agent initialization on the server.\nfunc (c *Client) InitiateAgentProcessing(ctx context.Context, id string, interactive bool) error {\n\tbody := jsonBody(proto.AgentInitRequest{Interactive: interactive})\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/agent/init\", id), nil, body, http.Header{\"Content-Type\": []string{\"application/json\"}})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to initiate session agent processing: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"failed to initiate session agent processing: status code %d\", rsp.StatusCode)","sourceCodeStart":549,"sourceCodeEnd":585,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L549-L585","documentation":"Thrown by Client.AgentSummarizeSession in internal/client/proto.go when the underlying HTTP POST to /workspaces/{id}/agent/sessions/{sessionID}/summarize fails at the transport level (connection error, timeout, canceled context). The request never got a response, so the error is the wrapped network-layer error from c.post. Called via AgentSummarize.","triggerScenarios":"Calling AgentSummarize/AgentSummarizeSession when the crush server is down, the workspace id or session id is stale, the network is unreachable, the context deadline expires, or DNS resolution for the server host fails.","commonSituations":"Server restarted or crashed while the client session was open; laptop suspended mid-run killing the TCP connection; firewall dropping long-lived connections; server address misconfigured in client config; context canceled because the user aborted the operation.","solutions":["Check the wrapped cause to distinguish context.Canceled/deadline from dial errors.","Verify the crush server is running and reachable (curl the server health endpoint).","Retry the summarize request with a fresh context if the failure was a timeout.","Correct the server address/URL in the client configuration if it points to a dead host."],"exampleFix":"// before\nerr := client.AgentSummarize(ctx, wsID, sessionID)\nif err != nil {\n    return err\n}\n// after: retry transient transport failures with a timeout\nctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\ndefer cancel()\nvar lastErr error\nfor i := 0; i < 3; i++ {\n    if err := client.AgentSummarize(ctx, wsID, sessionID); err == nil {\n        lastErr = nil\n        break\n    } else if !errors.Is(err, context.DeadlineExceeded) && !isNetErr(err) {\n        lastErr = err\n        break\n    }\n    lastErr = err\n    time.Sleep(time.Second << i)\n}","handlingStrategy":"retry","validationCode":"// Reachability pre-check before calling AgentSummarize\nconn, err := net.DialTimeout(\"tcp\", serverAddr, 3*time.Second)\nif err != nil {\n    return fmt.Errorf(\"crush server unreachable at %s: %w\", serverAddr, err)\n}\nconn.Close()","typeGuard":"func isTransportError(err error) bool {\n    if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {\n        return true\n    }\n    var ne net.Error\n    return errors.As(err, &ne)\n}","tryCatchPattern":"err := client.AgentSummarize(ctx, wsID, sessionID)\nif err != nil {\n    if isTransportError(err) {\n        return retryWithBackoff(ctx, 3, func() error {\n            return client.AgentSummarize(ctx, wsID, sessionID)\n        })\n    }\n    return err\n}","preventionTips":["Use contexts with explicit timeouts for every client call","Health-check the server before issuing summarize requests","Distinguish context.Canceled (user abort) from real failures — never retry cancellations","Keep the server address in one validated config source"],"tags":["network","http-client","request-failed"],"backgroundTag":"http-request-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}