{"record":{"id":"4ac709bc4b80f3c6","repo":"charmbracelet/crush","slug":"failed-to-delete-workspace-w","errorCode":null,"errorMessage":"failed to delete workspace: %w","messagePattern":"failed to delete workspace: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":80,"sourceCode":"\t\treturn nil, fmt.Errorf(\"failed to get workspace: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif err := checkStatus(rsp); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get workspace: %w\", err)\n\t}\n\tvar ws proto.Workspace\n\tif err := json.NewDecoder(rsp.Body).Decode(&ws); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode workspace: %w\", err)\n\t}\n\treturn &ws, nil\n}\n\n// DeleteWorkspace deletes a workspace on the server.\nfunc (c *Client) DeleteWorkspace(ctx context.Context, id string) error {\n\tq := url.Values{\"client_id\": []string{c.clientID}}\n\trsp, err := c.delete(ctx, fmt.Sprintf(\"/workspaces/%s\", id), q, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to delete workspace: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"failed to delete workspace: status code %d\", rsp.StatusCode)\n\t}\n\treturn nil\n}\n\n// SetCurrentSession reports the client's current-session selection\n// for the named workspace. An empty sessionID clears the entry. The\n// request carries the process-scoped client ID minted in [NewClient]\n// as a query parameter so the server can route the update to the\n// correct [clientState] entry.\nfunc (c *Client) SetCurrentSession(ctx context.Context, workspaceID, sessionID string) error {\n\tq := url.Values{\"client_id\": []string{c.clientID}}\n\trsp, err := c.post(\n\t\tctx,\n\t\tfmt.Sprintf(\"/workspaces/%s/current-session\", workspaceID),","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L62-L98","documentation":"DeleteWorkspace wraps an error from the underlying c.delete transport call for DELETE /workspaces/{id}?client_id=... . This is raised before status checking, so it reflects a transport-level failure: the request never completed successfully at the HTTP layer. The wrapped cause (connection error, canceled context, etc.) is available via errors.Is/As.","triggerScenarios":"Calling client.DeleteWorkspace(ctx, id) when the server is down or unreachable, the connection is reset mid-request, or the context is canceled before the DELETE completes.","commonSituations":"crush server stopped between listing and deleting a workspace; network blip on a laptop switching networks; context timeout too short for the delete; wrong server address after config change.","solutions":["Check the server is running and reachable before deleting.","Retry the delete with backoff; deletes are idempotent enough to tolerate re-issue (a 404 on retry means it succeeded).","Confirm the server URL/port in the client configuration.","Inspect errors.Is(err, context.Canceled) to avoid retrying caller-initiated cancels."],"exampleFix":"// before\nif err := client.DeleteWorkspace(ctx, id); err != nil { return err }\n// after: retry transient transport errors\nerr := client.DeleteWorkspace(ctx, id)\nfor i := 0; err != nil && i < 3; i++ {\n    if errors.Is(err, context.Canceled) { return err }\n    time.Sleep(time.Duration(1<<i) * 100 * time.Millisecond)\n    err = client.DeleteWorkspace(ctx, id)\n}","handlingStrategy":"retry","validationCode":"if !serverReachable(serverURL) { // e.g. net.DialTimeout probe\n    return fmt.Errorf(\"skip delete: server unreachable\")\n}","typeGuard":null,"tryCatchPattern":"err := client.DeleteWorkspace(ctx, id)\nif err != nil {\n    if errors.Is(err, context.Canceled) { return err }\n    // transport error: retry once; a 404 on retry means success\n    if rerr := client.DeleteWorkspace(ctx, id); rerr != nil && !strings.Contains(rerr.Error(), \"404\") {\n        return rerr\n    }\n}","preventionTips":["Keep the server process supervised (auto-restart).","Use retries with exponential backoff for deletes.","Treat 404 as idempotent success.","Avoid holding short contexts over delete operations."],"tags":["network","http-client","workspace"],"backgroundTag":"connection-refused","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}