can1357/oh-my-pi · error · GitHubError

proxy returned malformed release payload

Error message

proxy returned malformed release payload

What it means

`_release_from` converts a release object from the gh-proxy into `ReleaseInfo`. If the value returned for a release is not a JSON object, the client raises `GitHubError(500, ...)` with this message instead of failing later on field access. It indicates the proxy violated the expected release payload shape.

Source

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


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),
        run_id=int(data.get("run_id") or 0),
        name=str(data.get("name") or ""),
        status=str(data.get("status") or ""),
        conclusion=str(data["conclusion"]) if data.get("conclusion") is not None else None,
        html_url=str(data.get("html_url") or ""),
        failed_steps=tuple(str(step) for step in data.get("failed_steps") or []),
    )


def _release_from(data: Any) -> ReleaseInfo:
    if not isinstance(data, dict):
        raise GitHubError(500, "proxy returned malformed release payload")
    name = data.get("name")
    return ReleaseInfo(
        tag=str(data.get("tag") or ""),
        name=str(name) if name is not None else None,
        draft=bool(data.get("draft")),
        prerelease=bool(data.get("prerelease")),
        html_url=str(data.get("html_url") or ""),
        asset_names=tuple(str(asset) for asset in data.get("asset_names") or []),
    )


def _repo_from(data: Any) -> RepoInfo:
    if not isinstance(data, dict):
        raise GitHubError(500, "proxy returned malformed repo payload")
    return RepoInfo(
        full_name=str(data["full_name"]),
        default_branch=str(data["default_branch"]),
        clone_url=str(data["clone_url"]),

View on GitHub (pinned to 9690622007)

Solutions

  1. Capture and inspect the raw response body from the proxy for get_release_by_tag
  2. Bring proxy and client library versions into agreement on the release schema
  3. Confirm the request reaches the real gh-proxy service, not an error page from an intermediary

Example fix

# before
release = client.get_release_by_tag(repo, tag)
# after
try:
    release = client.get_release_by_tag(repo, tag)
except GitHubError as e:
    if "malformed release payload" in str(e):
        release = None  # fall back to manual tag handling
    else:
        raise
Defensive patterns

Strategy: type-guard

Validate before calling

release_payload = fetch_raw_release(repo, tag)
if not isinstance(release_payload, dict):
    raise ValueError(f"proxy release payload is {type(release_payload).__name__}, expected object")

Type guard

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

Try / catch

try:
    release = client.get_release_by_tag(repo, tag)
except GitHubError as e:
    if "malformed release payload" in str(e):
        log.warning("release schema mismatch", extra={"repo": repo, "tag": tag})
        release = None
    else:
        raise

Prevention

When it happens

Trigger: `get_release_by_tag` receiving a non-dict for the release — e.g. the proxy returned `null`/a string when the release lookup result shape differs, or an intermediary error body was parsed as the release.

Common situations: Proxy/client version skew after a release-schema change, custom proxy returning plain tag strings, gateway error pages, or a forked proxy with a different contract.

Understand the failure class

Related errors


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