gastownhall/beads · error
failed to fetch issues since %s: %w
Error message
failed to fetch issues since %s: %w
What it means
FetchIssuesSince wraps any Execute failure with this message, including the RFC3339 `since` timestamp in the text. The wrapped cause is the underlying failure for that page fetch (GraphQL errors, rate limiting, retries exhausted, HTTP errors, auth).
Source
Thrown at internal/linear/client.go:600
return nil, fmt.Errorf("pagination limit exceeded: stopped after %d pages", MaxPages)
}
variables := map[string]interface{}{
"filter": filter,
"first": MaxPageSize,
}
if cursor != "" {
variables["after"] = cursor
}
req := &GraphQLRequest{
Query: issuesQuery,
Variables: variables,
}
data, err := c.Execute(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to fetch issues since %s: %w", sinceStr, err)
}
var issuesResp IssuesResponse
if err := json.Unmarshal(data, &issuesResp); err != nil {
return nil, fmt.Errorf("failed to parse issues response: %w", err)
}
allIssues = append(allIssues, issuesResp.Issues.Nodes...)
if !issuesResp.Issues.PageInfo.HasNextPage {
break
}
cursor = issuesResp.Issues.PageInfo.EndCursor
}
return allIssues, nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Unwrap the error to see the root cause after 'since <timestamp>: '
- If rate-limited, wait for the reset (check X-RateLimit-Requests-Reset) and retry
- Verify the API token is still valid and can read the team
- Confirm the since timestamp is a sane RFC3339 time (not zero/epoch)
- Check Linear status page during widespread failures
Example fix
// before
issues, err := client.FetchIssuesSince(ctx, "open", since)
// after: retry with backoff on wrapped rate-limit errors
issues, err := client.FetchIssuesSince(ctx, "open", since)
if err != nil && strings.Contains(err.Error(), "max retries") {
time.Sleep(rateLimitReset - time.Now().Sub(time.Time{})) // or requeue the job
issues, err = client.FetchIssuesSince(ctx, "open", since)
} Defensive patterns
Strategy: try-catch
Validate before calling
if client.TeamID == "" || token == "" || since.IsZero() {
return errors.New("linear: TEAM_ID, token, and non-zero since are required")
} Try / catch
issues, err := client.FetchIssuesSince(ctx, "open", since)
if err != nil {
if strings.Contains(err.Error(), "max retries") || strings.Contains(err.Error(), "rate limited") {
// transient: requeue with the same watermark so nothing is lost
return requeueSync(since, err)
}
return fmt.Errorf("sync failed permanently: %w", err)
} Prevention
- Keep the since watermark persistent so retries resume exactly
- Back off on rate limits before re-running large deltas
- Validate the token/team at startup, not mid-sync
- Advance the watermark only after a fully successful fetch
When it happens
Trigger: Execute failure inside the FetchIssuesSince pagination loop: malformed or invalid updatedAt filter (GraphQL error), expired API token, 429 retries exhausted, network failure, or 4xx/5xx HTTP response from Linear.
Common situations: Rate-limit exhaustion during a large incremental sync; a since timestamp formatted unexpectedly causing a Linear filter validation error; revoked OAuth token with a failing refresh (401 path).
Related errors
- failed to fetch issues: %w
- failed to update project: %w
- failed to list projects: %w
- missing external ref for Linear issue %s
- Linear project milestone is missing id
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/7f64bbd959a20d8e.
Report an issue: GitHub.