gastownhall/beads · error

no runs found for workflow '%s'

Error message

no runs found for workflow '%s'

What it means

Raised when `gh run list` succeeds but returns zero runs for the given workflow name hint (cmd/bd/gate.go:1001). The workflow name parsed fine but GitHub has no matching runs, so no run ID can be discovered.

Source

Thrown at cmd/bd/gate.go:1001

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 same
// injected ghCommandRunner seam used everywhere else in the gh:run/gh:pr
// checks also covers cross-repo discovery, keeping that path unit-testable
// without a live `gh` CLI (standards note on the SF1 review).
func discoverRunIDByWorkflowNameInRepoWithRunner(workflowHint, repo string, runGH ghCommandRunner) (string, error) {
	// Query GitHub directly for this workflow (efficient, avoids limit issues)
	runs, err := queryGitHubRunsForWorkflowInRepoWithRunner(workflowHint, 5, repo, runGH)
	if err != nil {
		return "", fmt.Errorf("failed to query workflow runs: %w", err)
	}

	if len(runs) == 0 {
		return "", fmt.Errorf("no runs found for workflow '%s'", workflowHint)
	}

	// Take the most recent run (gh returns newest-first)
	// This is deterministic: "most recent" is a total ordering by creation time
	return fmt.Sprintf("%d", runs[0].DatabaseID), nil
}

// checkGHRun checks a GitHub Actions workflow run gate.
// When persistAwaitID is nil, workflow-name discovery stays in-memory only.
func checkGHRun(gate *types.Issue, persistAwaitID func(gateID, runID string) error) (resolved, escalated bool, reason string, err error) {
	return checkGHRunWithRunner(gate, persistAwaitID, runGHCommand)
}

func checkGHRunWithRunner(gate *types.Issue, persistAwaitID func(gateID, runID string) error, runGH ghCommandRunner) (resolved, escalated bool, reason string, err error) {
	if gate.AwaitID == "" {
		return false, false, "no run ID specified - set await_id or use workflow name hint", nil
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Trigger the workflow once (`gh workflow run <name>` or push) so a run exists
  2. Check the hint matches the workflow's name/filename: `gh workflow list --repo <owner/repo>`
  3. Verify you're querying the intended repo (cross-repo metadata may point elsewhere)
  4. Replace the hint with a concrete numeric run ID via `gh run list --workflow=<name>`

Example fix

// before
await_id: "deploy.yml"  // never triggered
// after
gh workflow run deploy.yml   # or set await_id to an existing numeric run ID
await_id: "1234567890"
Defensive patterns

Strategy: validation

Validate before calling

out, err := exec.Command("gh", "run", "list", "--workflow", hint, "--repo", repo, "--limit", "1").Output()
if err != nil || len(strings.Fields(string(out))) == 0 {
    // hint has no runs — trigger the workflow or use a numeric run ID
}

Try / catch

if resolved, esc, reason, err := checkGHRun(gate); reason != "" && strings.Contains(reason, "no runs found") {
    // not a hard error: trigger the workflow or fall back to a numeric await_id
}

Prevention

When it happens

Trigger: A gh:run gate uses a non-numeric await_id workflow hint and the API query returns an empty array — the workflow exists in the repo but has never run, or the name doesn't match any executed workflow.

Common situations: Typo in the workflow name hint, workflow defined only on another branch (never run on default branch), workflow file recently added and not yet triggered, querying a fork/cross-repo with no runs.

Related errors


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