{"record":{"id":"c75a4aafe72aa3fa","repo":"gastownhall/beads","slug":"failed-to-fetch-team-labels-w","errorCode":null,"errorMessage":"failed to fetch team labels: %w","messagePattern":"failed to fetch team labels: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/linear/client.go","lineNumber":699,"sourceCode":"\tvar after *string\n\tfor {\n\t\tvars := map[string]interface{}{\n\t\t\t\"teamId\": c.TeamID,\n\t\t\t\"first\":  pageSize,\n\t\t\t\"after\":  nil,\n\t\t}\n\t\tif after != nil {\n\t\t\tvars[\"after\"] = *after\n\t\t}\n\n\t\treq := &GraphQLRequest{\n\t\t\tQuery:     query,\n\t\t\tVariables: vars,\n\t\t}\n\n\t\tdata, err := c.Execute(ctx, req)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to fetch team labels: %w\", err)\n\t\t}\n\n\t\tvar page struct {\n\t\t\tTeam struct {\n\t\t\t\tLabels *struct {\n\t\t\t\t\tNodes    []Label `json:\"nodes\"`\n\t\t\t\t\tPageInfo struct {\n\t\t\t\t\t\tHasNextPage bool   `json:\"hasNextPage\"`\n\t\t\t\t\t\tEndCursor   string `json:\"endCursor\"`\n\t\t\t\t\t} `json:\"pageInfo\"`\n\t\t\t\t} `json:\"labels\"`\n\t\t\t} `json:\"team\"`\n\t\t}\n\t\tif err := json.Unmarshal(data, &page); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse team labels response: %w\", err)\n\t\t}\n\t\tif page.Team.Labels == nil {\n\t\t\treturn nil, fmt.Errorf(\"no labels connection found for team\")","sourceCodeStart":681,"sourceCodeEnd":717,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/linear/client.go#L681-L717","documentation":"GetTeamLabels calls Linear's GraphQL API page-by-page to collect all issue labels for a team. Any error returned from the underlying Execute call (transport failure, HTTP error, GraphQL error) is wrapped with this prefix so callers know the failure happened while fetching label pages.","triggerScenarios":"c.Execute fails during any pagination iteration: network timeout, non-2xx HTTP status, invalid/expired API key, rate limiting (429), or GraphQL errors in the response body.","commonSituations":"Expired or rotated LINEAR_API_KEY, corporate proxy/firewall blocking api.linear.app, Linear rate limits hit while paginating many label pages, transient DNS or TLS failures.","solutions":["Inspect the wrapped cause (%w chain) for the actual transport/HTTP/GraphQL error and address it specifically.","Verify the API key is valid and not expired by calling a trivial query (e.g. `viewer { id }`).","Retry the call with backoff if the cause is a 429 or transient network error — Linear rate limits are documented in response headers.","Check network/proxy configuration if the cause is connection-level (timeouts, DNS, TLS)."],"exampleFix":"// before\nif err != nil {\n    return nil, fmt.Errorf(\"failed to fetch team labels: %w\", err)\n}\n// after\nif err != nil {\n    var rlErr *RateLimitError\n    if errors.As(err, &rlErr) {\n        time.Sleep(rlErr.RetryAfter)\n        continue // retry this page\n    }\n    return nil, fmt.Errorf(\"failed to fetch team labels (page %d): %w\", pageNum, err)\n}","handlingStrategy":"retry","validationCode":"if os.Getenv(\"LINEAR_API_KEY\") == \"\" {\n    return errors.New(\"LINEAR_API_KEY not set\")\n}\n// optional preflight:\n// resp, err := http.Post(endpoint, ..., `{\"query\":\"{ viewer { id } }\"}`)","typeGuard":null,"tryCatchPattern":"labels, err := client.GetTeamLabels(ctx)\nif err != nil {\n    var netErr net.Error\n    if errors.As(err, &netErr) && netErr.Timeout() {\n        // retry with backoff\n    }\n    return fmt.Errorf(\"label cache build failed: %w\", err)\n}","preventionTips":["Preflight the API key with a trivial viewer query at startup.","Implement exponential backoff for 429 responses.","Run periodic health checks against api.linear.app.","Log the unwrapped cause chain for faster diagnosis."],"tags":["network","graphql","linear","wrapping-error"],"backgroundTag":"api-request-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}