{"record":{"id":"8da0a03862482d1a","repo":"charmbracelet/crush","slug":"failed-to-get-permissions-skip-requests-w","errorCode":null,"errorMessage":"failed to get permissions skip requests: %w","messagePattern":"failed to get permissions skip requests: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/client/proto.go","lineNumber":751,"sourceCode":"\n// SetPermissionsSkipRequests sets the skip-requests flag for a workspace.\nfunc (c *Client) SetPermissionsSkipRequests(ctx context.Context, id string, skip bool) error {\n\trsp, err := c.post(ctx, fmt.Sprintf(\"/workspaces/%s/permissions/skip\", id), nil, jsonBody(proto.PermissionSkipRequest{Skip: skip}), http.Header{\"Content-Type\": []string{\"application/json\"}})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to set permissions skip requests: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn fmt.Errorf(\"failed to set permissions skip requests: status code %d\", rsp.StatusCode)\n\t}\n\treturn nil\n}\n\n// GetPermissionsSkipRequests retrieves the skip-requests flag for a workspace.\nfunc (c *Client) GetPermissionsSkipRequests(ctx context.Context, id string) (bool, error) {\n\trsp, err := c.get(ctx, fmt.Sprintf(\"/workspaces/%s/permissions/skip\", id), nil, nil)\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"failed to get permissions skip requests: %w\", err)\n\t}\n\tdefer rsp.Body.Close()\n\tif rsp.StatusCode != http.StatusOK {\n\t\treturn false, fmt.Errorf(\"failed to get permissions skip requests: status code %d\", rsp.StatusCode)\n\t}\n\tvar skip proto.PermissionSkipRequest\n\tif err := json.NewDecoder(rsp.Body).Decode(&skip); err != nil {\n\t\treturn false, fmt.Errorf(\"failed to decode permissions skip requests: %w\", err)\n\t}\n\treturn skip.Skip, nil\n}\n\n// GetConfig retrieves the workspace-specific configuration.\nfunc (c *Client) GetConfig(ctx context.Context, id string) (*config.Config, error) {\n\trsp, err := c.get(ctx, fmt.Sprintf(\"/workspaces/%s/config\", id), nil, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get config: %w\", err)\n\t}","sourceCodeStart":733,"sourceCodeEnd":769,"githubUrl":"https://github.com/charmbracelet/crush/blob/7944b8e52225d8805e31eacbf7ef24856b0dfb7a/internal/client/proto.go#L733-L769","documentation":"GetPermissionsSkipRequests wraps any transport-level failure of the GET request to /workspaces/{id}/permissions/skip with this message. It only fires when c.get itself returns an error (connection refused, context canceled, invalid URL, etc.) — non-200 responses produce the separate 'status code %d' variant. The underlying cause is preserved via %w.","triggerScenarios":"Calling GetPermissionsSkipRequests when the server is unreachable or the connection is refused, when ctx is canceled/times out before the request completes, or when the request URL is malformed (e.g. workspace id containing characters that break the URL).","commonSituations":"Dev server not started; wrong host/port configuration; VPN or proxy dropping the connection; context deadline exceeded during slow network; workspace id with spaces or slashes.","solutions":["Print/unwrap the wrapped cause (errors.Unwrap or %v of the error) to see the concrete transport failure.","Verify the crush server/daemon is running and reachable at the configured address (curl the endpoint).","Check ctx deadlines: pass context.WithTimeout with a generous timeout or ensure no premature cancelation.","Sanitize/validate the workspace id before building the URL."],"exampleFix":"// before\nctx := context.Background()\nskip, err := c.GetPermissionsSkipRequests(ctx, wsID)\n// after: bounded, inspectable request\nctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\ndefer cancel()\nskip, err := c.GetPermissionsSkipRequests(ctx, wsID)\nif err != nil {\n    log.Fatalf(\"get permissions skip failed: %+v\", err) // shows wrapped cause\n}","handlingStrategy":"retry","validationCode":"// Go: probe the endpoint before the real call\nreq, _ := http.NewRequestWithContext(ctx, http.MethodGet, baseURL+\"/health\", nil)\nif _, err := http.DefaultClient.Do(req); err != nil {\n    return fmt.Errorf(\"server not reachable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"skip, err := c.GetPermissionsSkipRequests(ctx, id)\nif err != nil {\n    if errors.Is(ctx.Err(), context.DeadlineExceeded) {\n        // increase timeout and retry\n    }\n    return fmt.Errorf(\"get permissions skip: %w\", err)\n}","preventionTips":["Always pass a context with a sane timeout.","Check daemon/server liveness before API calls.","Sanitize path parameters (workspace id) used in URLs.","Unwrap errors with %w so root causes remain inspectable."],"tags":["http","network","api-client","wrapped-error"],"backgroundTag":"request-transport-failed","analyzedSha":"7944b8e52225d8805e31eacbf7ef24856b0dfb7a","analyzedAt":"2026-08-29T12:48:59.079Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}