{"record":{"id":"4bdb8c8421d8a4f7","repo":"can1357/oh-my-pi","slug":"proxy-returned-malformed-issue-summary-payload","errorCode":null,"errorMessage":"proxy returned malformed issue summary payload","messagePattern":"proxy returned malformed issue summary payload","errorType":"exception","errorClass":"GitHubError","httpStatus":500,"severity":"error","filePath":"python/robomp/src/proxy_client.py","lineNumber":623,"sourceCode":"def _issue_from(data: Any) -> IssueInfo:\n    if not isinstance(data, dict):\n        raise GitHubError(500, \"proxy returned malformed issue payload\")\n    labels = data.get(\"labels\") or []\n    return IssueInfo(\n        repo=str(data[\"repo\"]),\n        number=int(data[\"number\"]),\n        title=str(data.get(\"title\") or \"\"),\n        body=str(data.get(\"body\") or \"\"),\n        state=str(data.get(\"state\") or \"open\"),\n        author=str(data.get(\"author\") or \"\"),\n        labels=tuple(str(x) for x in labels),\n        is_pull_request=bool(data.get(\"is_pull_request\", False)),\n    )\n\n\ndef _issue_summary_from(data: Any) -> IssueSummary:\n    if not isinstance(data, dict):\n        raise GitHubError(500, \"proxy returned malformed issue summary payload\")\n    return IssueSummary(\n        repo=str(data[\"repo\"]),\n        number=int(data[\"number\"]),\n        title=str(data.get(\"title\") or \"\"),\n        state=str(data.get(\"state\") or \"\"),\n        author=str(data.get(\"author\") or \"\"),\n        labels=tuple(str(x) for x in (data.get(\"labels\") or [])),\n        comments=int(data.get(\"comments\") or 0),\n        updated_at=str(data.get(\"updated_at\") or \"\"),\n        created_at=str(data.get(\"created_at\") or \"\"),\n        html_url=str(data.get(\"html_url\") or \"\"),\n        state_reason=str(data.get(\"state_reason\") or \"\"),\n        is_pull_request=bool(data.get(\"is_pull_request\")),\n    )\n\n\ndef _index_entry_from(data: Any) -> IssueIndexEntry:\n    if not isinstance(data, dict):","sourceCodeStart":605,"sourceCodeEnd":641,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/robomp/src/proxy_client.py#L605-L641","documentation":"GitHubError(500) raised by _issue_summary_from when an element of the proxy's issue list/search results is not a JSON object. Each list/search item must be a dict to build an IssueSummary; a non-dict item breaks the pagination contract and aborts the whole listing.","triggerScenarios":"Calling list_issues() or search_issues() when the proxy returns a JSON array containing a non-object element (null, string, number) instead of an issue-summary object.","commonSituations":"Proxy serialization bug emitting null for tombstoned/deleted issues inside a list; proxy version skew where search results wrap items differently; truncated/mangled response body parsed into scalars; gateway injecting an error string into the items array.","solutions":["Dump the raw list/search response from the proxy and locate the non-object element (its index in the array).","Check the proxy version against the client's expected schema; upgrade or roll back the proxy to the matching version.","Look for proxy-side serialization errors for specific issues (e.g. deleted or permission-denied issues serialized as null).","Retry the listing; if intermittent, wrap list_issues/search_issues in a retry with backoff.","Filter/patch at the proxy to omit or repair malformed entries instead of emitting them."],"exampleFix":"# before\nfor s in client.list_issues(\"org/repo\", state=\"open\"):\n    print(s.title)  # GitHubError 500 on one malformed item\n\n# after\ntry:\n    summaries = client.list_issues(\"org/repo\", state=\"open\")\nexcept GitHubError as e:\n    if e.status == 500:\n        summaries = []  # degrade: log and continue with empty page\n    else:\n        raise","handlingStrategy":"type-guard","validationCode":"data = resp.json()\nitems = data if isinstance(data, list) else []\nbad = [i for i, x in enumerate(items) if not isinstance(x, dict)]\nif bad:\n    raise RuntimeError(f\"non-object issue summary entries at indices {bad}\")","typeGuard":"def is_issue_summary(data: object) -> bool:\n    return isinstance(data, dict) and \"repo\" in data and \"number\" in data","tryCatchPattern":"try:\n    summaries = client.list_issues(\"org/repo\", state=\"open\")\nexcept GitHubError as e:\n    if e.status == 500 and \"malformed issue summary\" in str(e):\n        summaries = []\n    else:\n        raise","preventionTips":["Validate one page of proxy list output in CI against the IssueSummary schema.","Check the proxy for null-emitting serialization of deleted/hidden issues.","Keep proxy and client schema versions in lockstep.","Fall back to per-issue get_issue on listing failure rather than aborting the job."],"tags":["proxy","payload-validation","list-response","github"],"backgroundTag":"proxy-malformed-payload","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}