wtfutil/wtf · error

failed to parse JQL search response

Error message

failed to parse JQL search response: %v

What it means

searchWithNewAPI fails with this error when utils.ParseJSON cannot decode the /rest/api/3/search/jql response body into the JQLSearchResult struct. The HTTP call succeeded but the body doesn't match the expected JSON shape (issues array, pagination fields, etc.).

Solutions

  1. Log the raw response body to see the actual JSON returned
  2. Compare the JQLSearchResult struct tags with the current /rest/api/3/search/jql response schema from Atlassian docs
  3. Bypass/update any proxy that might rewrite the response
  4. Update the client (or struct tags) to the current API response format

Example fix

// before
issues []struct {
    Key string `json:"key"`
}
// after (match current API payload)
issues []struct {
    Key    string `json:"key"`
    Fields struct {
        Summary string `json:"summary"`
    } `json:"fields"`
} `json:"issues"`
Defensive patterns

Strategy: type-guard

Type guard

func looksLikeJQLSearchResponse(body []byte) bool {
    var probe struct {
        Issues []json.RawMessage `json:"issues"`
    }
    return json.Unmarshal(body, &probe) == nil
}

Try / catch

result, err := widget.IssuesFor(ctx, username, jql)
if err != nil {
    if strings.Contains(err.Error(), "failed to parse JQL search response") {
        log.Printf("response schema drift or proxy interference: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: Jira returns 200 with a body whose JSON keys/types differ from JQLSearchResult (API shape change), or an error payload/HTML page arrives with a 200-like status, or a truncated/garbled body from a proxy.

Common situations: Atlassian changing field names/types in search/jql responses, an API gateway or proxy returning an HTML error page, a stale fork of the client missing new response fields, gzip/encoding issues from intermediaries.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03). Data as JSON: /api/errors/e1bbe1f163c2ff20. Report an issue: GitHub.

Appendix: source

Thrown at modules/jira/client.go:234

	jqlURL := fmt.Sprintf("/rest/api/3/search/jql?%s", v.Encode())

	resp, err := widget.jiraRequest(jqlURL)
	if err != nil {
		return nil, err
	}

	// Parse the JQL response which contains issue IDs
	type JQLSearchResult struct {
		Issues []struct {
			ID string `json:"id"`
		} `json:"issues"`
	}

	jqlResult := &JQLSearchResult{}
	err = utils.ParseJSON(jqlResult, bytes.NewReader(resp))
	if err != nil {
		return nil, fmt.Errorf("failed to parse JQL search response: %v", err)
	}

	if len(jqlResult.Issues) == 0 {
		// Return empty result if no issues found
		return &SearchResult{Issues: []Issue{}}, nil
	}

	// Now get full issue details for each ID
	searchResult := &SearchResult{Issues: []Issue{}}

	for i, issue := range jqlResult.Issues {
		// Limit to prevent too many API calls
		if i >= 20 {
			break
		}

		fullIssue, err := widget.getIssueByID(issue.ID)
		if err != nil {

View on GitHub (pinned to bb838c1ccb)