{"record":{"id":"5cab0d8d272587ac","repo":"can1357/oh-my-pi","slug":"proxy-returned-malformed-pr-review-payload","errorCode":null,"errorMessage":"proxy returned malformed pr_review payload","messagePattern":"proxy returned malformed pr_review payload","errorType":"exception","errorClass":"GitHubError","httpStatus":500,"severity":"error","filePath":"python/robomp/src/proxy_client.py","lineNumber":698,"sourceCode":"\n\ndef _review_comment_from(data: Any) -> ReviewCommentInfo:\n    if not isinstance(data, dict):\n        raise GitHubError(500, \"proxy returned malformed review_comment payload\")\n    line = data.get(\"line\")\n    return ReviewCommentInfo(\n        id=int(data.get(\"id\") or 0),\n        author=str(data.get(\"author\") or \"\"),\n        body=str(data.get(\"body\") or \"\"),\n        path=str(data.get(\"path\") or \"\"),\n        line=line if isinstance(line, int) else None,\n        created_at=str(data.get(\"created_at\") or \"\"),\n    )\n\n\ndef _pr_review_from(data: Any) -> PullRequestReviewInfo:\n    if not isinstance(data, dict):\n        raise GitHubError(500, \"proxy returned malformed pr_review payload\")\n    return PullRequestReviewInfo(\n        id=int(data.get(\"id\") or 0),\n        author=str(data.get(\"author\") or \"\"),\n        body=str(data.get(\"body\") or \"\"),\n        state=str(data.get(\"state\") or \"\"),\n        submitted_at=str(data.get(\"submitted_at\") or \"\"),\n    )\n\n\ndef _pr_file_from(data: Any) -> PullRequestFileInfo:\n    if not isinstance(data, dict):\n        raise GitHubError(500, \"proxy returned malformed pr_file payload\")\n    return PullRequestFileInfo(\n        path=str(data.get(\"path\") or \"\"),\n        status=str(data.get(\"status\") or \"\"),\n        additions=int(data.get(\"additions\") or 0),\n        deletions=int(data.get(\"deletions\") or 0),\n        patch=str(data.get(\"patch\") or \"\"),","sourceCodeStart":680,"sourceCodeEnd":716,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/python/robomp/src/proxy_client.py#L680-L716","documentation":"GitHubError(500) raised by _pr_review_from when a PR review payload from the proxy is not a JSON object. list_pr_reviews expects each review to be a dict and submit_pr_review expects the resulting review object; non-dict responses violate the proxy contract.","triggerScenarios":"Calling list_pr_reviews() with a non-object element in the reviews array, or submit_pr_review() when the proxy acknowledges the review submission with null/a scalar instead of a PullRequestReviewInfo object.","commonSituations":"Proxy in ACK-only mode after submitting a review; null entries for pending/discarded reviews in a listing; proxy version skew changing the review envelope; body-rewriting middleware.","solutions":["Inspect the raw proxy response for the PR reviews endpoint to see the actual non-dict body.","For submit_pr_review: verify whether the review was actually created on GitHub, then re-fetch via list_pr_reviews instead of resubmitting.","Align the proxy version with the client; redeploy if schemas diverge.","Retry the listing; on persistent failure fall back to the GitHub web/API view of reviews.","Report the contract violation to the proxy maintainers with the response body."],"exampleFix":"# before\nreview = client.submit_pr_review(\"org/repo\", pr, \"APPROVE\", \"lgtm\")  # GitHubError 500\n\n# after\ntry:\n    review = client.submit_pr_review(\"org/repo\", pr, \"APPROVE\", \"lgtm\")\nexcept GitHubError as e:\n    if e.status == 500:\n        reviews = client.list_pr_reviews(\"org/repo\", pr)  # verify it landed\n        review = reviews[-1] if reviews else None\n    else:\n        raise","handlingStrategy":"try-catch","validationCode":"raw = resp.json()\nif not isinstance(raw, dict):\n    raise RuntimeError(f\"proxy review payload not an object: {raw!r}\")","typeGuard":"def is_pr_review(data: object) -> bool:\n    return isinstance(data, dict) and \"state\" in data","tryCatchPattern":"try:\n    review = client.submit_pr_review(\"org/repo\", pr, \"APPROVE\")\nexcept GitHubError as e:\n    if e.status == 500 and \"malformed pr_review payload\" in str(e):\n        reviews = client.list_pr_reviews(\"org/repo\", pr)  # verify it landed; do not resubmit blindly\n        review = reviews[-1] if reviews else None\n    else:\n        raise","preventionTips":["Never resubmit a review on this error — verify via list_pr_reviews first (duplicate approvals are harmful).","Ensure the proxy returns the created review object, not an ACK string.","Add contract tests covering submit_pr_review's response shape.","Watch for pending/discarded reviews serialized as null by the proxy."],"tags":["proxy","payload-validation","pull-request","review","github"],"backgroundTag":"proxy-malformed-payload","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}