{"record":{"id":"c0f6b3e341760a24","repo":"wtfutil/wtf","slug":"jira-search-failed-v","errorCode":null,"errorMessage":"JIRA search failed: %v","messagePattern":"JIRA search failed: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"modules/jira/client.go","lineNumber":204,"sourceCode":"\tif username != \"\" {\n\t\t// Convert JQL with username to account ID\n\t\tconvertedJQL, err := widget.ConvertJQLWithUsername(username)\n\t\tif err != nil {\n\t\t\treturn &SearchResult{}, fmt.Errorf(\"failed to convert username %s to account ID: %v\", username, err)\n\t\t}\n\t\tquery = append(query, convertedJQL)\n\t}\n\n\tif jql != \"\" {\n\t\tquery = append(query, jql)\n\t}\n\n\t// Try the new API v3 search/jql endpoint\n\tjqlQuery := strings.Join(query, \" AND \")\n\tsearchResult, err := widget.searchWithNewAPI(jqlQuery)\n\tif err != nil {\n\t\t// If new API fails, return the error\n\t\treturn &SearchResult{}, fmt.Errorf(\"JIRA search failed: %v\", err)\n\t}\n\n\treturn searchResult, nil\n}\n\n// searchWithNewAPI uses the new /rest/api/3/search/jql endpoint\nfunc (widget *Widget) searchWithNewAPI(jql string) (*SearchResult, error) {\n\t// First, get issue IDs using the new endpoint\n\tv := url.Values{}\n\tv.Set(\"jql\", jql)\n\tv.Set(\"maxResults\", \"20\") // Limit to avoid too many API calls\n\n\tjqlURL := fmt.Sprintf(\"/rest/api/3/search/jql?%s\", v.Encode())\n\n\tresp, err := widget.jiraRequest(jqlURL)\n\tif err != nil {\n\t\treturn nil, err\n\t}","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/wtfutil/wtf/blob/bb838c1ccb0f0f3223690df44afdec663d622881/modules/jira/client.go#L186-L222","documentation":"IssuesFor fails with this error when searchWithNewAPI - the Jira Cloud v3 /rest/api/3/search/jql endpoint - returns an error. The error propagates the underlying cause, meaning the search request itself failed (transport, auth, or API rejection); it is not a parse failure of a successful response.","triggerScenarios":"IssuesFor -> searchWithNewAPI receives a non-2xx or transport error from /rest/api/3/search/jql: 401/403 (bad token), 400 (malformed JQL), 429, or network failure to api.atlassian.com.","commonSituations":"Expired/revoked Jira API tokens, JQL composed from username conversion plus user JQL that is syntactically invalid, Atlassian deprecating/changing the search/jql endpoint, corporate proxy blocking api.atlassian.com.","solutions":["Read the wrapped error (%v) for the HTTP status or transport cause","Validate the API token and site URL in the Jira widget config","Test the joined JQL manually in Jira's search to find syntax problems","Check Atlassian's API changelog for search/jql endpoint changes and update the client"],"exampleFix":"// before\nquery := \"assignee = \" + username\n// after (valid converted clause)\nquery := \"accountID in (\\\"5f2a3b4c5d6e7f8a9b0c1d2e\\\")\"","handlingStrategy":"try-catch","validationCode":"// sanity-check the composed JQL before the API call\njqlQuery := strings.Join(query, \" AND \")\nif strings.TrimSpace(jqlQuery) == \"\" || strings.Count(jqlQuery, \"(\") != strings.Count(jqlQuery, \")\") {\n    return fmt.Errorf(\"refusing to send unbalanced/empty JQL: %q\", jqlQuery)\n}","typeGuard":null,"tryCatchPattern":"result, err := widget.IssuesFor(ctx, username, jql)\nif err != nil {\n    if strings.Contains(err.Error(), \"JIRA search failed\") {\n        log.Printf(\"search/jql endpoint failed: %v - check token/JQL/Atlassian status\", err)\n        // optional: fall back to legacy /rest/api/3/search\n    }\n    return err\n}","preventionTips":["Rotate Jira API tokens before expiry","Verify combined JQL clauses in Jira's own search UI first","Subscribe to Atlassian API change/deprecation notices","Add backoff retry for 429/5xx from search/jql"],"tags":["jira","api","go","http"],"backgroundTag":"jira-search-api-failed","analyzedSha":"bb838c1ccb0f0f3223690df44afdec663d622881","analyzedAt":"2026-09-03T17:02:45.030Z","contentChangedAt":"2026-09-03T17:02:45.030Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}