gastownhall/beads · error
failed to fetch milestone by IID %d: %w
Error message
failed to fetch milestone by IID %d: %w
What it means
FetchMilestoneByIID queries /projects/:id/milestones with an iids[] filter via doRequest, which handles auth, retries, and HTTP errors. This error wraps any doRequest failure — network errors, timeouts, context cancellation, or HTTP error statuses (401/403/500) returned by GitLab. It is raised before JSON parsing, so the request never completed successfully.
Source
Thrown at internal/gitlab/client.go:446
var milestones []Milestone
if err := json.Unmarshal(respBody, &milestones); err != nil {
return nil, fmt.Errorf("failed to parse milestones response: %w", err)
}
return milestones, nil
}
// FetchMilestoneByIID retrieves a single milestone by its project-scoped IID.
// Returns nil if no milestone matches the given IID.
func (c *Client) FetchMilestoneByIID(ctx context.Context, iid int) (*Milestone, error) {
params := map[string]string{
"iids[]": strconv.Itoa(iid),
}
urlStr := c.buildURL("/projects/"+c.projectPath()+"/milestones", params)
respBody, _, err := c.doRequest(ctx, http.MethodGet, urlStr, nil)
if err != nil {
return nil, fmt.Errorf("failed to fetch milestone by IID %d: %w", iid, err)
}
var milestones []Milestone
if err := json.Unmarshal(respBody, &milestones); err != nil {
return nil, fmt.Errorf("failed to parse milestone response: %w", err)
}
if len(milestones) == 0 {
return nil, nil
}
return &milestones[0], nil
}
// CreateMilestone creates a new milestone in GitLab.
func (c *Client) CreateMilestone(ctx context.Context, title, description string) (*Milestone, error) {
body := map[string]interface{}{
"title": title,View on GitHub (pinned to 71377f2769)
Solutions
- Unwrap the error to read the HTTP status or transport cause (url.Error, context.DeadlineExceeded)
- Check token validity and read_api scope; re-authenticate if 401/403
- Verify the client's configured project path matches the milestone's project
- For timeouts, increase the client timeout or retry; confirm network egress to the GitLab host
Example fix
// before
m, err := client.FetchMilestoneByIID(ctx, iid)
if err != nil { return err }
// after
m, err := client.FetchMilestoneByIID(ctx, iid)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
return retryWithBackoff(...)
}
return fmt.Errorf("milestone %d lookup: %w", iid, err)
} Defensive patterns
Strategy: retry
Validate before calling
if iid <= 0 {
return fmt.Errorf("invalid milestone IID %d", iid)
}
if err := ctx.Err(); err != nil {
return err
} Type guard
func isAuthError(err error) bool {
return strings.Contains(err.Error(), "401") || strings.Contains(err.Error(), "403")
} Try / catch
m, err := client.FetchMilestoneByIID(ctx, iid)
if err != nil {
if isAuthError(err) {
return fmt.Errorf("check GITLAB token/scopes: %w", err) // don't retry auth
}
if isTransient(err) {
return fetchMilestoneWithRetry(ctx, iid)
}
return err
} Prevention
- Validate IIDs are positive integers before querying
- Refresh tokens before expiry and grant read_api scope
- Set client timeouts generously for slower self-hosted GitLab instances
- Confirm CI runners have network egress to the GitLab host
When it happens
Trigger: Calling Client.FetchMilestoneByIID with expired/invalid credentials, a misconfigured project path, network outage, or a cancelled context while the filtered milestones query runs.
Common situations: PAT expired or lacking read_api scope; project namespace changed/renamed so the URL 404s; VPN or proxy blocking the GitLab host in CI; context deadline exceeded on slow GitLab instances.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- failed to fetch milestones: %w
- request failed (attempt %d/%d): %w
- failed to fetch issue %d: %w
- failed to create milestone: %w
- failed to update milestone: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/96236dcaab5b1ed8.
Report an issue: GitHub.