{"record":{"id":"f12bbd195a4c2c16","repo":"gastownhall/beads","slug":"failed-to-fetch-issue-d-w","errorCode":null,"errorMessage":"failed to fetch issue %d: %w","messagePattern":"failed to fetch issue (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/gitlab/client.go","lineNumber":401,"sourceCode":"\trespBody, _, err := c.doRequest(ctx, http.MethodGet, urlStr, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to get issue links: %w\", err)\n\t}\n\n\tvar links []IssueLink\n\tif err := json.Unmarshal(respBody, &links); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse issue links response: %w\", err)\n\t}\n\n\treturn links, nil\n}\n\n// FetchIssueByIID retrieves a single issue by its project-scoped IID.\nfunc (c *Client) FetchIssueByIID(ctx context.Context, iid int) (*Issue, error) {\n\turlStr := c.buildURL(\"/projects/\"+c.projectPath()+\"/issues/\"+strconv.Itoa(iid), nil)\n\trespBody, _, err := c.doRequest(ctx, http.MethodGet, urlStr, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to fetch issue %d: %w\", iid, err)\n\t}\n\n\tvar issue Issue\n\tif err := json.Unmarshal(respBody, &issue); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to parse issue response: %w\", err)\n\t}\n\n\treturn &issue, nil\n}\n\n// FetchMilestones retrieves milestones from the project with optional state filter.\n// state can be: \"active\", \"closed\", or \"\" (all).\nfunc (c *Client) FetchMilestones(ctx context.Context, state string) ([]Milestone, error) {\n\tparams := map[string]string{\n\t\t\"per_page\": strconv.Itoa(MaxPageSize),\n\t}\n\tif state != \"\" {\n\t\tparams[\"state\"] = state","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/gitlab/client.go#L383-L419","documentation":"FetchIssueByIID performs a GET to /projects/:id/issues/:iid via doRequest, which handles auth, retries, and HTTP error responses. This error wraps any doRequest failure: network errors, timeouts, context cancellation, or non-success HTTP statuses returned by GitLab. It is raised before JSON parsing, so the request itself never completed successfully.","triggerScenarios":"Calling Client.FetchIssueByIID with an iid that does not exist (GitLab returns 404), an invalid/expired token (401/403), no network connectivity, or a context that was cancelled before/at request time.","commonSituations":"Typo'd or stale issue IID cached from another project; wrong project configured on the client so the scoped IID resolves to nothing; PAT expired or lacking read_api scope; offline/VPN-down environments.","solutions":["Unwrap the error (errors.Unwrap/errors.As on *gitlab.APIError or url.Error) to see whether it is 404, 401/403, or a transport failure","Verify the configured project matches the project that owns the IID and that the IID is an integer within the project","Check token validity and scopes (read_api) and re-authenticate if 401/403","For 404, confirm the issue exists via the GitLab web UI or API search; for network errors, retry with backoff after checking connectivity"],"exampleFix":"// before\nissue, err := client.FetchIssueByIID(ctx, iid)\nif err != nil { return err }\n// after\nissue, err := client.FetchIssueByIID(ctx, iid)\nif err != nil {\n    if errors.Is(err, context.Canceled) { return err }\n    log.Printf(\"fetch issue %d failed: %v\", iid, err)\n    return fmt.Errorf(\"lookup issue %d: %w\", iid, err)\n}","handlingStrategy":"retry","validationCode":"if iid <= 0 {\n    return fmt.Errorf(\"invalid issue IID %d\", iid)\n}\nif err := ctx.Err(); err != nil {\n    return err // context already cancelled\n}","typeGuard":"func isNotFound(err error) bool {\n    return strings.Contains(err.Error(), \"404\")\n}","tryCatchPattern":"issue, err := client.FetchIssueByIID(ctx, iid)\nif err != nil {\n    if isNotFound(err) {\n        return nil // treat missing issue as empty, not fatal\n    }\n    if errors.Is(err, context.DeadlineExceeded) || isTransient(err) {\n        return fetchWithRetry(ctx, iid)\n    }\n    return fmt.Errorf(\"fetch issue %d: %w\", iid, err)\n}","preventionTips":["Validate IIDs are positive integers and belong to the configured project","Keep tokens fresh and scoped (read_api); rotate before expiry","Set a sane HTTP timeout and rely on the client's built-in retry for transient failures","Cache known-good IIDs and validate against search when a fetch 404s"],"tags":["gitlab","network","http","api"],"backgroundTag":"http-request-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}