{"record":{"id":"cde074c65014eeef","repo":"charmbracelet/crush","slug":"failed-to-delete-workspace-status-code-d","errorCode":null,"errorMessage":"failed to delete workspace: status code %d","messagePattern":"failed to delete workspace: status code (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":84,"sourceCode":"\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),\n\t\tq,\n\t\tjsonBody(proto.CurrentSession{SessionID: sessionID}),\n\t\thttp.Header{\"Content-Type\": []string{\"application/json\"}},\n\t)","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L66-L102","documentation":"DeleteWorkspace requires an exact HTTP 200; any other status (e.g. 403, 404, 409, 500) produces this error with the status code embedded. Unlike checkStatus-based paths this branch reports only the numeric code, so the server's error detail body is not included. It means the server actively rejected or failed the delete.","triggerScenarios":"Calling client.DeleteWorkspace(ctx, id) when the workspace does not exist (404), the client_id does not own the workspace (403/409), or the server errors while removing state (5xx).","commonSituations":"Deleting an already-deleted workspace from another client session; ownership mismatch because the client was restarted and minted a new client ID (NewClient generates a process-scoped ID); stale workspace list from before a server restart.","solutions":["Treat 404 as success (workspace already gone) and ignore it.","Re-list workspaces (ListWorkspaces) to refresh ids before deleting.","If ownership errors occur, create the workspace with the current client (CreateWorkspace stamps ws.ClientID) or restart from a fresh list.","Check server logs for the status code to find the 5xx cause."],"exampleFix":"// before\nif err := client.DeleteWorkspace(ctx, id); err != nil { return err }\n// after: tolerate already-deleted\nif err := client.DeleteWorkspace(ctx, id); err != nil {\n    if strings.Contains(err.Error(), \"status code 404\") {\n        return nil\n    }\n    return err\n}","handlingStrategy":"validation","validationCode":"// verify existence and ownership before deleting\nwss, err := client.ListWorkspaces(ctx)\nif err != nil { return err }\nowned := false\nfor _, w := range wss {\n    if w.ID == id && w.ClientID == myClientID { owned = true }\n}\nif !owned { return fmt.Errorf(\"workspace %q not owned by this client\", id) }","typeGuard":null,"tryCatchPattern":"err := client.DeleteWorkspace(ctx, id)\nvar statusErr interface{ StatusCode() int }\nswitch {\ncase err == nil:\n    return nil\ncase strings.Contains(err.Error(), \"status code 404\"):\n    return nil // already gone\ndefault:\n    return err\n}","preventionTips":["Refresh the workspace list before deleting.","Remember client IDs are process-scoped and change on restart.","Treat 404 as success in cleanup paths.","Match on the embedded status code, not the generic message."],"tags":["http-status","http-client","workspace"],"backgroundTag":"http-status-mismatch","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}