wtfutil/wtf · error
failed to parse issue %s: %v
Error message
failed to parse issue %s: %v
What it means
getIssueByID fails with this error when the individual issue fetched from Jira cannot be parsed into the Issue struct via utils.ParseJSON. The issue ID is included so the failing record is identifiable. Like error 78, the HTTP request succeeded but the payload doesn't fit the expected struct.
Source
Thrown at modules/jira/client.go:273
continue
}
searchResult.Issues = append(searchResult.Issues, *fullIssue)
}
return searchResult, nil
} // getIssueByID fetches full issue details by ID
func (widget *Widget) getIssueByID(issueID string) (*Issue, error) {
url := fmt.Sprintf("/rest/api/3/issue/%s", issueID)
resp, err := widget.jiraRequest(url)
if err != nil {
return nil, err
}
issue := &Issue{}
err = utils.ParseJSON(issue, bytes.NewReader(resp))
if err != nil {
return nil, fmt.Errorf("failed to parse issue %s: %v", issueID, err)
}
return issue, nil
}
func buildJql(key string, value string) string {
return fmt.Sprintf("%s = \"%s\"", key, value)
}
/* -------------------- Unexported Functions -------------------- */
func (widget *Widget) jiraRequest(path string) ([]byte, error) {
url := fmt.Sprintf("%s%s", widget.settings.domain, path)
req, err := http.NewRequest("GET", url, http.NoBody)
if err != nil {
return nil, err
}View on GitHub (pinned to bb838c1ccb)
Solutions
- Log the raw body for the failing issue ID to see the mismatch
- Update the Issue struct's JSON tags to match the current Jira API v3 issue payload
- Make brittle fields nullable/omitempty and tolerate nulls in parsing
- Check whether an intermediary (proxy/SSO) is rewriting the response
Example fix
// before
type Issue struct {
Assignee struct{ Name string `json:"name"` } `json:"assignee"` // removed field
}
// after
type Issue struct {
Assignee *struct {
AccountID string `json:"accountId"`
} `json:"assignee"` // nullable pointer, current field
} Defensive patterns
Strategy: type-guard
Type guard
func looksLikeIssue(body []byte) bool {
var probe struct {
ID string `json:"id"`
Key string `json:"key"`
Fields json.RawMessage `json:"fields"`
}
return json.Unmarshal(body, &probe) == nil && probe.Key != ""
} Try / catch
issue, err := widget.getIssueByID(ctx, issueID)
if err != nil {
if strings.Contains(err.Error(), "failed to parse issue") {
log.Printf("issue %s payload not parseable - check schema/custom fields: %v", issueID, err)
}
return err
} Prevention
- Keep the Issue struct's tags in sync with Jira API v3 issue payloads
- Model custom fields as json.RawMessage to avoid type mismatches
- Use pointers for nullable fields (assignee, resolution) so nulls parse
- Test parsing against a representative sample of real issues, including ones with custom fields
When it happens
Trigger: The issue endpoint returns a body whose fields don't match the Issue struct (missing/renamed keys, unexpected types), or an HTML/error page is returned instead of issue JSON.
Common situations: Jira issue containing custom fields with unexpected shapes, deprecated field names after a Jira Cloud API update, proxy/SSO page injection, issues with null values where the struct expects objects.
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to parse JQL search response: %v
- failed to marshal request: %v
- failed to extract account ID from converted query: %s
- decoding response: %w
- no conversion result for username: %s
AI-assisted analysis of wtfutil/wtf@bb838c1ccb (2026-09-03).
Data as JSON: /api/errors/8da27449986362f0.
Report an issue: GitHub.