{"record":{"id":"d76118842fe67b52","repo":"gastownhall/beads","slug":"parse-issue-response-w","errorCode":null,"errorMessage":"parse issue response: %w","messagePattern":"parse issue response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/jira/client.go","lineNumber":246,"sourceCode":"\t\t}\n\t\tnextPageToken = result.NextPageToken\n\t}\n\n\treturn allIssues, nil\n}\n\n// GetIssue fetches a single Jira issue by key (e.g., \"PROJ-123\").\nfunc (c *Client) GetIssue(ctx context.Context, key string) (*Issue, error) {\n\tapiURL := fmt.Sprintf(\"%s/issue/%s?fields=%s\", c.apiBase(), url.PathEscape(key), searchFields)\n\n\tbody, err := c.doRequest(ctx, \"GET\", apiURL, nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get issue %s: %w\", key, err)\n\t}\n\n\tvar issue Issue\n\tif err := json.Unmarshal(body, &issue); err != nil {\n\t\treturn nil, fmt.Errorf(\"parse issue response: %w\", err)\n\t}\n\n\treturn &issue, nil\n}\n\n// CreateIssue creates a new issue in Jira.\n// fields should include \"project\", \"summary\", \"issuetype\", and optionally other fields.\nfunc (c *Client) CreateIssue(ctx context.Context, fields map[string]interface{}) (*Issue, error) {\n\tpayload := map[string]interface{}{\"fields\": fields}\n\tdata, err := json.Marshal(payload)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"marshal create request: %w\", err)\n\t}\n\n\tapiURL := fmt.Sprintf(\"%s/issue\", c.apiBase())\n\n\tbody, err := c.doRequest(ctx, \"POST\", apiURL, data)\n\tif err != nil {","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/jira/client.go#L228-L264","documentation":"GetIssue wraps json.Unmarshal errors for the GET /issue/{key} response. The request succeeded but the body is not valid JSON or doesn't match the Issue struct (id, key, self, fields). Thrown also from CreateIssue's hydration step. Typically indicates an HTML/error body returned with a success status.","triggerScenarios":"GET /issue/{key} returns 200 with a non-JSON body: proxy/SSO HTML page, an API-gateway error envelope, or a response shape incompatible with the Issue struct.","commonSituations":"Corporate proxies or captive portals rewriting responses; wrong base URL routed to a login page; Jira plugins modifying issue payloads; mismatched API version returning unexpected schema.","solutions":["Inspect the raw body (log a prefix of it) to identify HTML vs JSON vs unexpected schema.","Confirm the base URL and APIVersion so requests hit /rest/api/N not a UI route.","Test the endpoint with curl and the same auth to bypass/identify interception layers.","Update struct tags if your Jira version changed the issue response shape."],"exampleFix":"// before\nvar issue Issue\nif err := json.Unmarshal(body, &issue); err != nil {\n    return nil, fmt.Errorf(\"parse issue response: %w\", err)\n}\n// after: surface body for diagnosis\nif err := json.Unmarshal(body, &issue); err != nil {\n    return nil, fmt.Errorf(\"parse issue response: %w (body: %.200s)\", err, string(body))\n}","handlingStrategy":"type-guard","validationCode":"func isJSONBody(b []byte) bool {\n    s := bytes.TrimLeft(b, \" \\t\\r\\n\")\n    return len(s) > 0 && (s[0] == '{' || s[0] == '[')\n}","typeGuard":"func issueLooksValid(i *jira.Issue) bool {\n    return i != nil && i.ID != \"\" && i.Key != \"\"\n}","tryCatchPattern":"issue, err := client.GetIssue(ctx, key)\nif err != nil && strings.Contains(err.Error(), \"parse issue response\") {\n    // non-JSON 2xx body: check proxy/SSO interception and base URL\n    log.Printf(\"issue fetch for %s returned unparseable body; bypass gateway and retry\", key)\n    return\n}","preventionTips":["Route REST calls directly to Jira, bypassing gateways that inject HTML","Re-verify Issue struct tags after Jira platform upgrades","Confirm base URL resolves to the REST API, not a login page","Alert on repeated parse failures — they usually indicate infra, not code"],"tags":["jira","json","http-response","go"],"backgroundTag":"invalid-json-response","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}