gastownhall/beads · error
parse gh output: %w
Error message
parse gh output: %w
What it means
After a successful `gh run list` invocation, its JSON output is unmarshaled into []GHWorkflowRun. If gh's output is not the expected JSON array (empty output, truncated output, human-readable output because --json was dropped/unsupported, or an old gh version with a different schema), this error wraps the json.Unmarshal failure.
Source
Thrown at cmd/bd/gate.go:971
"--workflow", workflow,
"--json", "databaseId,name,status,conclusion,createdAt,workflowName",
"--limit", fmt.Sprintf("%d", limit),
}
if repo != "" {
args = append(args, "--repo", repo)
}
output, stderr, err := runGH(args...)
if err != nil {
if len(stderr) > 0 {
return nil, fmt.Errorf("gh run list --workflow=%s failed: %s", workflow, string(stderr))
}
return nil, fmt.Errorf("gh run list: %w", err)
}
var runs []GHWorkflowRun
if err := json.Unmarshal(output, &runs); err != nil {
return nil, fmt.Errorf("parse gh output: %w", err)
}
return runs, nil
}
// discoverRunIDByWorkflowName queries GitHub for the most recent run of a workflow.
// Returns (runID, error). This is ZFC-compliant: "most recent run" is deterministic.
func discoverRunIDByWorkflowName(workflowHint string) (string, error) {
return discoverRunIDByWorkflowNameInRepo(workflowHint, "")
}
func discoverRunIDByWorkflowNameInRepo(workflowHint, repo string) (string, error) {
return discoverRunIDByWorkflowNameInRepoWithRunner(workflowHint, repo, runGHCommand)
}
// discoverRunIDByWorkflowNameInRepoWithRunner is the runner-injectable form of
// discoverRunIDByWorkflowNameInRepo. checkGHRunWithRunner's cross-repo branch
// must call this (not discoverRunIDByWorkflowNameInRepo directly) so the sameView on GitHub (pinned to 71377f2769)
Solutions
- Run `gh run list --workflow=<name> -R <repo> --json ...` manually and confirm valid JSON is printed (pipe to `jq .`).
- Upgrade gh CLI to a recent version so the --json field set matches GHWorkflowRun.
- If a custom ghCommandRunner is injected, ensure it returns raw gh stdout unmodified (no banners, no reformatting).
- Add logging around output length/content to spot truncation or proxy-injected HTML, then fix the transport (proxy, pager: set GH_PAGER= / --no-pager).
Example fix
// before (fake runner returning human output)
return []byte(" Showing 2 of 2 runs"), nil, nil
// after
return []byte(`[{"databaseId":123,"status":"completed","conclusion":"success"}]`), nil, nil Defensive patterns
Strategy: validation
Validate before calling
// sanity-check gh output before handing it to parsers
out, err := exec.Command("gh", "run", "list", "--workflow=ci.yml", "-R", repo, "--json", "databaseId").Output()
if err == nil {
var probe []json.RawMessage
if json.Unmarshal(out, &probe) != nil || len(out) == 0 {
return errors.New("gh did not return a JSON array; check gh version and --json support")
}
} Try / catch
runs, err := queryGitHubRunsForWorkflow("ci.yml", 5)
if err != nil {
if strings.HasPrefix(err.Error(), "parse gh output:") {
log.Printf("gh returned unexpected output; upgrade gh or fix runner stdout: %v", err)
return nil
}
return err
} Prevention
- Pin/upgrade gh to a version supporting all --json fields your parser expects.
- Never pipe gh output through text filters before parsing; disable pagers (GH_PAGER=).
- Ensure custom runners return raw gh stdout only.
- Unit-test the JSON contract with a golden fixture of gh run list output.
When it happens
Trigger: queryGitHubRunsForWorkflowInRepoWithRunner receives malformed/empty stdout from runGH — e.g. gh emitted a warning banner to stdout, a proxy returned HTML, output was truncated, or a fake runner returned non-JSON.
Common situations: Very old gh versions lacking the --json fields used; piping gh through text processors that altered output; capturing human-readable output (missing --json flag) in a custom runner; API degradation returning partial responses.
Related errors
- unable to parse plugin file: %w
- metadata must be a JSON object: %w
- gh CLI not found: install from https://cli.github.com
- gh run list --workflow=%s failed: %s
- gh run list: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/9028f8f979cfb4dd.
Report an issue: GitHub.