gastownhall/beads · error

gh run list: %w

Error message

gh run list: %w

What it means

When the `gh run list` subprocess fails but gh produced no stderr output, bd wraps the raw exec error as "gh run list: %w". This is the opaque-failure branch: the process exited non-zero without any diagnostic text, typically because gh itself could not be executed rather than rejected by the API.

Source

Thrown at cmd/bd/gate_discover.go:470

		"--limit", strconv.Itoa(limit),
	}

	if branch != "" {
		args = append(args, "--branch", branch)
	}
	if repo != "" {
		args = append(args, "--repo", repo)
	}
	if workflow != "" {
		args = append(args, "--workflow", workflow)
	}

	output, stderr, err := runGH(args...)
	if err != nil {
		if len(stderr) > 0 {
			return nil, fmt.Errorf("gh run list failed: %s", 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
}

// matchGateToRun finds the best matching run for a gate using heuristics.
// If the gate has a workflow name hint in AwaitID, only runs matching that workflow are considered.
//
// foreignRepo must be true when runs were queried from a repo other than the
// current one (SF1: a gate whose metadata.repo targets another repository).
// In that case the local commit SHA and branch name are meaningless - they
// describe the current checkout, not the foreign repo - so the commit/branch
// heuristics are skipped entirely rather than comparing against them anyway.

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run `gh run list --limit 1` manually to reproduce the spawn failure outside bd
  2. Check the gh binary is executable and matches your OS/arch: `file $(which gh)`
  3. Remove or fix any `gh` wrapper/shim on PATH shadowing the real CLI (`type -a gh`)
  4. Reinstall gh from https://cli.github.com if the binary is corrupt
  5. Retry if the failure was a transient timeout during process startup

Example fix

// before
$ bd gate discover
Error: gh run list: fork/exec /usr/local/bin/gh: exec format error
// after
$ file /usr/local/bin/gh  # wrong arch
$ brew reinstall gh
$ bd gate discover
Defensive patterns

Strategy: fallback

Validate before calling

// preflight that gh can actually be spawned with a trivial command
if out, err := exec.Command("gh", "--version").Output(); err != nil || len(out) == 0 {
  return fmt.Errorf("gh present on PATH but not executable; reinstall gh")
}

Try / catch

if _, err := queryGitHubRunsInRepo(branch, limit, repo, workflow); err != nil {
  if strings.HasPrefix(err.Error(), "gh run list:") { // no stderr — spawn/exec failure
    // fall back to a manual path or degraded mode; do not blind-retry
    return fmt.Errorf("gh could not be executed: %w (check $(which gh))", err)
  }
  return err
}

Prevention

When it happens

Trigger: runGH(args...) returns err with empty stderr: gh binary exists in PATH but is not executable, the OS fails to spawn it (ENOEXEC, EACCES), context/timeout killed the process before output, or gh crashed without writing stderr.

Common situations: A `gh` shim/wrapper script on PATH with a bad shebang; wrong-architecture gh binary; file permissions stripped (chmod -x); sandboxed CI blocking process execution; PATH pointing to a stub named gh that isn't the real CLI.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/46a481285d4e8c9a. Report an issue: GitHub.