can1357/oh-my-pi · error · GitHubError

proxy returned malformed workflow run payload

Error message

proxy returned malformed workflow run payload

What it means

`_workflow_run_from` converts a single workflow-run entry returned by the gh-proxy into a `WorkflowRunInfo`. If the proxy response contains an element that is not a JSON object, the client raises `GitHubError(500, ...)` rather than crash with a confusing AttributeError. It signals a broken contract between proxy and client, not a GitHub API problem.

Source

Thrown at python/robomp/src/proxy_client.py:552

        body: dict[str, Any] = {
            "repo": repo,
            "workspace_key": workspace_key,
            "branch": branch,
            "tag": tag,
            "expected_head": expected_head,
        }
        if slot_uid is not None:
            body["slot_uid"] = slot_uid
        data = self._post("/gh/v1/git/push_release", body)
        return PushResult(head=str(data.get("head") or expected_head), branch=str(data.get("branch") or branch))


# ---------- payload helpers ----------


def _workflow_run_from(data: Any) -> WorkflowRunInfo:
    if not isinstance(data, dict):
        raise GitHubError(500, "proxy returned malformed workflow run payload")
    return WorkflowRunInfo(
        id=int(data.get("id") or 0),
        name=str(data.get("name") or ""),
        event=str(data.get("event") or ""),
        status=str(data.get("status") or ""),
        conclusion=str(data["conclusion"]) if data.get("conclusion") is not None else None,
        head_branch=str(data["head_branch"]) if data.get("head_branch") is not None else None,
        head_sha=str(data.get("head_sha") or ""),
        html_url=str(data.get("html_url") or ""),
        run_attempt=int(data.get("run_attempt") or 1),
    )


def _workflow_job_from(data: Any) -> WorkflowJobInfo:
    if not isinstance(data, dict):
        raise GitHubError(500, "proxy returned malformed workflow job payload")
    return WorkflowJobInfo(
        id=int(data.get("id") or 0),

View on GitHub (pinned to 9690622007)

Solutions

  1. Check the raw HTTP response body from the proxy for the affected call (log it before parsing)
  2. Upgrade or align proxy server and client library versions so the run schema matches
  3. Verify the proxy (not an intermediary like an auth gateway or CDN) produced the response

Example fix

# before
runs = client.list_workflow_runs(repo)
# after
data = client._request(...)  # or add logging
assert all(isinstance(r, dict) for r in runs_payload), f"unexpected proxy payload: {type(runs_payload[0])}"
runs = [ _workflow_run_from(r) for r in runs_payload ]
Defensive patterns

Strategy: type-guard

Validate before calling

# validate the raw payload items before mapping
runs_payload = fetch_raw_runs(repo)
if not isinstance(runs_payload, list) or not all(isinstance(r, dict) for r in runs_payload):
    raise ValueError("proxy workflow-runs payload malformed")

Type guard

def is_run_payload(v: object) -> TypeGuard[dict]:
    return isinstance(v, dict) and "id" in v

Try / catch

try:
    runs = client.list_workflow_runs(repo)
except GitHubError as e:
    if "malformed workflow run payload" in str(e):
        log.warning("proxy/client schema mismatch on workflow runs", extra={"repo": repo})
        runs = []
    else:
        raise

Prevention

When it happens

Trigger: `list_workflow_runs` receiving a proxy payload whose run entries are non-dict values — e.g. the proxy returned an error string/array in the items list, or proxy and client versions disagree on the response schema.

Common situations: Proxy deployed at an older/newer version than the client library, a gateway returning HTML/JSON arrays on error, or a custom/forked proxy emitting a different run shape.

Understand the failure class

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/2a6a4b0c487fbf60. Report an issue: GitHub.