{"record":{"id":"82ce5ea12df77240","repo":"gastownhall/beads","slug":"failed-to-parse-issues-response-w","errorCode":null,"errorMessage":"failed to parse issues response: %w","messagePattern":"failed to parse issues response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/gitlab/client.go","lineNumber":259,"sourceCode":"\n\t\tparams := map[string]string{\n\t\t\t\"per_page\": strconv.Itoa(MaxPageSize),\n\t\t\t\"page\":     strconv.Itoa(page),\n\t\t}\n\t\tif state != \"\" && state != \"all\" {\n\t\t\tparams[\"state\"] = state\n\t\t}\n\t\tapplyFilter(params, filter)\n\n\t\turlStr := c.buildURL(c.issuesBasePath(), params)\n\t\trespBody, headers, err := c.doRequest(ctx, http.MethodGet, urlStr, nil)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to fetch issues: %w\", err)\n\t\t}\n\n\t\tvar issues []Issue\n\t\tif err := json.Unmarshal(respBody, &issues); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to parse issues response: %w\", err)\n\t\t}\n\n\t\tallIssues = append(allIssues, issues...)\n\n\t\t// Check for next page\n\t\tnextPage := headers.Get(\"X-Next-Page\")\n\t\tif nextPage == \"\" {\n\t\t\tbreak\n\t\t}\n\t\tpage++\n\n\t\t// Guard against infinite pagination loops from malformed responses\n\t\tif page > MaxPages {\n\t\t\treturn nil, fmt.Errorf(\"pagination limit exceeded: stopped after %d pages\", MaxPages)\n\t\t}\n\t}\n\n\treturn filterByProject(allIssues, filter), nil","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/gitlab/client.go#L241-L277","documentation":"FetchIssues failed to JSON-decode a GitLab issues list response into []Issue. The library throws this when the HTTP response body is not the expected JSON array of issue objects, so the pagination loop aborts with the underlying json.Unmarshal error wrapped.","triggerScenarios":"GET /projects/:id/issues returns a body that does not unmarshal into []Issue — e.g. a proxy/login page returning HTML, a JSON error object instead of an array, or a GitLab schema change adding a field with an incompatible type.","commonSituations":"Wrong base URL pointing at a non-GitLab host (HTML 200 response), an auth proxy or SSO redirect page, GitLab version with changed field types (e.g. dates or IDs changing shape), or a reverse proxy returning an error page with 200.","solutions":["Check baseURL/token config: curl the same URL and confirm the body is a JSON array of issues","Inspect the wrapped %w error for the exact Unmarshal mismatch (field/type) and compare against the Issue struct for your GitLab version","Upgrade/downgrade the library to match your GitLab server version","If behind a proxy, bypass it or fix it so API responses pass through untouched"],"exampleFix":"// before\nissues, err := client.FetchIssues(ctx, \"opened\")\nif err != nil { panic(err) }\n// after\nissues, err := client.FetchIssues(ctx, \"opened\")\nif err != nil {\n\tlog.Fatalf(\"gitlab fetch failed (check baseURL/token/GitLab version): %v\", err)\n}","handlingStrategy":"try-catch","validationCode":"resp, _ := http.Get(baseURL + \"/api/v4/projects/\" + url.PathEscape(project) + \"/issues?per_page=1\")\nbody, _ := io.ReadAll(resp.Body)\nif !json.Valid(body) || body[0] != '[' {\n\treturn fmt.Errorf(\"endpoint does not return a JSON array of issues\")\n}","typeGuard":"func isJSONParseError(err error) bool {\n\tvar jsonErr *json.UnmarshalTypeError\n\treturn errors.As(err, &jsonErr) || strings.Contains(err.Error(), \"failed to parse issues response\")\n}","tryCatchPattern":"issues, err := client.FetchIssues(ctx, \"opened\")\nif err != nil {\n\tvar synErr *net.OpError\n\tif errors.Is(err, context.Canceled) { return err }\n\tlog.Printf(\"gitlab response unparseable (check baseURL/proxy/GitLab version): %v\", err)\n\treturn nil // or fall back to cached issues\n}","preventionTips":["Point the client at the direct GitLab API URL, not an SSO/proxy front end","Use a token with read_api scope and test it with a one-issue curl first","Keep the library version aligned with your GitLab server version","Log raw response bodies on failure to diagnose schema drift quickly"],"tags":["gitlab","json","network"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}