gastownhall/beads · error
failed to parse gh output: %w
Error message
failed to parse gh output: %w
What it means
Wraps a JSON unmarshal failure when parsing `gh run view --json status,conclusion,name` output (cmd/bd/gate.go:1085). gh exited 0 but produced output that doesn't fit the expected ghRunStatus shape.
Source
Thrown at cmd/bd/gate.go:1085
args = append(args, "--repo", repo)
}
stdout, stderr, runErr := runGH(args...)
if runErr != nil {
// Check if gh CLI is not found
if strings.Contains(string(stderr), "command not found") ||
strings.Contains(runErr.Error(), "executable file not found") {
return false, false, "", fmt.Errorf("gh CLI not installed")
}
// Check if run not found
if strings.Contains(string(stderr), "not found") {
return false, true, "workflow run not found", nil
}
return false, false, "", fmt.Errorf("gh run view failed: %s", string(stderr))
}
var status ghRunStatus
if parseErr := json.Unmarshal(stdout, &status); parseErr != nil {
return false, false, "", fmt.Errorf("failed to parse gh output: %w", parseErr)
}
// Evaluate status
switch status.Status {
case "completed":
switch status.Conclusion {
case "success":
return true, false, fmt.Sprintf("workflow '%s' succeeded", status.Name), nil
case "failure":
return false, true, fmt.Sprintf("workflow '%s' failed", status.Name), nil
case "cancelled", "canceled":
return false, true, fmt.Sprintf("workflow '%s' was canceled", status.Name), nil
case "skipped":
return true, false, fmt.Sprintf("workflow '%s' was skipped", status.Name), nil
default:
return false, true, fmt.Sprintf("workflow '%s' concluded with %s", status.Name, status.Conclusion), nil
}
case "in_progress", "queued", "pending", "waiting":View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped parse error (%w) for the JSON offset/type mismatch
- Upgrade the gh CLI (`gh upgrade` or reinstall) to a version supporting `gh run view --json`
- Run `gh run view <id> --json status,conclusion,name` manually to inspect raw output
- Confirm gh is not aliased/wrapped by a script polluting stdout
Example fix
// before gh version 0.9 (no --json on run view) // after brew upgrade gh && gh --version # >= 2.x
Defensive patterns
Strategy: validation
Validate before calling
if out, err := exec.Command("gh", "--version").Output(); err != nil || !strings.HasPrefix(string(out), "gh version 2") {
// upgrade gh: --json output required
} Try / catch
if _, _, _, err := checkGHRunStatus(runID); err != nil && strings.Contains(err.Error(), "failed to parse gh output") {
// capture raw output for diagnosis; likely gh version or environment issue
} Prevention
- Keep gh CLI current (>= 2.x)
- Avoid wrappers/aliases around gh that print to stdout
- Set GH_PAGER=cat to suppress pager output
When it happens
Trigger: gh succeeds but stdout is not the expected JSON — empty output, gh CLI version too old lacking --json fields, or gh emitting warnings/human text mixed into stdout.
Common situations: Ancient gh version (pre --json support), locale/env causing gh to print non-JSON to stdout, piping where stderr text lands in stdout, truncated output from a broken terminal wrapper.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- parsing JSON: %w
- parse gh output: %w
- failed to parse JSONL line: %w
- failed to parse memory record: %w
- failed to parse issue from JSONL: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/489c5020ba7ac405.
Report an issue: GitHub.