gastownhall/beads · error

search issues: %w

Error message

search issues: %w

What it means

SearchIssues wraps errors from doRequest (the HTTP GET to /search/jql or /search). It means the transport layer failed before a body could be parsed: non-2xx status, connection error, timeout, or canceled context. The library wraps it with the search context so callers know the JQL query itself failed at the HTTP level.

Source

Thrown at internal/jira/client.go:206

			"fields":     {searchFields},
			"maxResults": {fmt.Sprintf("%d", maxResults)},
		}
		if useV2Pagination {
			params.Set("startAt", fmt.Sprintf("%d", startAt))
		} else if nextPageToken != "" {
			params.Set("nextPageToken", nextPageToken)
		}

		// v3 uses /search/jql; v2 uses /search (both accept jql as a query param)
		searchPath := "search/jql"
		if useV2Pagination {
			searchPath = "search"
		}
		apiURL := fmt.Sprintf("%s/%s?%s", c.apiBase(), searchPath, params.Encode())

		body, err := c.doRequest(ctx, "GET", apiURL, nil)
		if err != nil {
			return nil, fmt.Errorf("search issues: %w", err)
		}

		var result SearchResult
		if err := json.Unmarshal(body, &result); err != nil {
			return nil, fmt.Errorf("parse search response: %w", err)
		}

		allIssues = append(allIssues, result.Issues...)

		if len(result.Issues) == 0 {
			break
		}
		if useV2Pagination {
			if startAt+len(result.Issues) >= result.Total {
				break
			}
			startAt += len(result.Issues)
			continue

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check wrapped error for HTTP status: fix auth (401/403) by regenerating the API token and using account email.
  2. If 404, set c.APIVersion appropriately ("2" for older Jira Server which lacks /search/jql).
  3. If 400, validate JQL syntax in the Jira UI search bar first.
  4. If 429 or timeout, back off and retry with a smaller maxResults or narrower JQL.

Example fix

// before: opaque failure
issues, err := client.SearchIssues(ctx, jql)
// after: retry transient failures
var issues []jira.Issue
err := retry(3, func() error {
    var e error
    issues, e = client.SearchIssues(ctx, jql)
    return e
})
Defensive patterns

Strategy: retry

Validate before calling

// Preflight auth and endpoint before searching:
resp, err := http.Get(client.URL + "/rest/api/3/myself") // expect 200 with valid basic auth
if err != nil || resp.StatusCode != 200 {
    return fmt.Errorf("Jira preflight failed: status %d", resp.StatusCode)
}

Type guard

func isRateLimit(err error) bool {
    return err != nil && (strings.Contains(err.Error(), "429") || strings.Contains(err.Error(), "rate"))
}

Try / catch

var issues []jira.Issue
backoff := time.Second
for attempt := 0; attempt < 3; attempt++ {
    issues, err = client.SearchIssues(ctx, jql)
    if err == nil { break }
    if isRateLimit(err) || errors.Is(err, context.DeadlineExceeded) {
        time.Sleep(backoff); backoff *= 2; continue
    }
    return err // non-transient: bad JQL, auth
}

Prevention

When it happens

Trigger: Any SearchIssues call where the HTTP request fails: 401/403 (bad API token), 404 (wrong API version path), 400 (malformed JQL), 429 (rate limit), network outage, or 30s client timeout on huge queries.

Common situations: Expired or wrong Atlassian API token; email vs username confusion in basic auth; Jira Server lacking the v3 /search/jql endpoint; JQL syntax errors rejected with 400; rate limiting during bulk syncs.

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/d19785dba0f3cee4. Report an issue: GitHub.