{"record":{"id":"66f4d9cb367d07cc","repo":"gastownhall/beads","slug":"failed-to-query-workflow-runs-w","errorCode":null,"errorMessage":"failed to query workflow runs: %w","messagePattern":"failed to query workflow runs: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/gate.go","lineNumber":997,"sourceCode":"func discoverRunIDByWorkflowName(workflowHint string) (string, error) {\n\treturn discoverRunIDByWorkflowNameInRepo(workflowHint, \"\")\n}\n\nfunc discoverRunIDByWorkflowNameInRepo(workflowHint, repo string) (string, error) {\n\treturn discoverRunIDByWorkflowNameInRepoWithRunner(workflowHint, repo, runGHCommand)\n}\n\n// discoverRunIDByWorkflowNameInRepoWithRunner is the runner-injectable form of\n// discoverRunIDByWorkflowNameInRepo. checkGHRunWithRunner's cross-repo branch\n// must call this (not discoverRunIDByWorkflowNameInRepo directly) so the same\n// injected ghCommandRunner seam used everywhere else in the gh:run/gh:pr\n// checks also covers cross-repo discovery, keeping that path unit-testable\n// without a live `gh` CLI (standards note on the SF1 review).\nfunc discoverRunIDByWorkflowNameInRepoWithRunner(workflowHint, repo string, runGH ghCommandRunner) (string, error) {\n\t// Query GitHub directly for this workflow (efficient, avoids limit issues)\n\truns, err := queryGitHubRunsForWorkflowInRepoWithRunner(workflowHint, 5, repo, runGH)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to query workflow runs: %w\", err)\n\t}\n\n\tif len(runs) == 0 {\n\t\treturn \"\", fmt.Errorf(\"no runs found for workflow '%s'\", workflowHint)\n\t}\n\n\t// Take the most recent run (gh returns newest-first)\n\t// This is deterministic: \"most recent\" is a total ordering by creation time\n\treturn fmt.Sprintf(\"%d\", runs[0].DatabaseID), nil\n}\n\n// checkGHRun checks a GitHub Actions workflow run gate.\n// When persistAwaitID is nil, workflow-name discovery stays in-memory only.\nfunc checkGHRun(gate *types.Issue, persistAwaitID func(gateID, runID string) error) (resolved, escalated bool, reason string, err error) {\n\treturn checkGHRunWithRunner(gate, persistAwaitID, runGHCommand)\n}\n\nfunc checkGHRunWithRunner(gate *types.Issue, persistAwaitID func(gateID, runID string) error, runGH ghCommandRunner) (resolved, escalated bool, reason string, err error) {","sourceCodeStart":979,"sourceCodeEnd":1015,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/gate.go#L979-L1015","documentation":"Wraps any failure from `gh run list` when resolving a gate's workflow-name hint to a numeric run ID. It is raised in discoverRunIDByWorkflowNameInRepoWithRunner (cmd/bd/gate.go:997) and bundles the underlying cause (gh CLI failure, stderr from GitHub, or JSON parse error) via %w.","triggerScenarios":"A gh:run gate whose await_id is a non-numeric workflow name hint is evaluated and queryGitHubRunsForWorkflowInRepoWithRunner fails: gh returns non-zero (auth error, network failure, unknown workflow) or its JSON output cannot be parsed.","commonSituations":"gh not authenticated (GH_TOKEN expired), wrong --repo slug, workflow file renamed/deleted so the name no longer matches, offline CI runner, gh CLI version emitting unexpected JSON.","solutions":["Run `gh run list --workflow=<name> --repo <owner/repo>` manually to see the real gh error wrapped underneath","Re-authenticate with `gh auth login` or refresh GH_TOKEN","Verify the workflow name matches the workflow file name exactly in the target repo","Check the repo slug in the gate metadata points at an accessible repository"],"exampleFix":"// before\ndiscoveredID, discoverErr = discoverRunIDByWorkflowNameInRepoWithRunner(gate.AwaitID, repo, runGH)\n// after\nif discoveredID, discoverErr = discoverRunIDByWorkflowNameInRepoWithRunner(gate.AwaitID, repo, runGH); discoverErr != nil {\n    log.Printf(\"gate %s: hint %s failed: %v\", gate.ID, gate.AwaitID, discoverErr) // inspect wrapped cause\n}","handlingStrategy":"retry","validationCode":"gh auth status && gh run list --workflow=<hint> --repo <owner/repo> --limit 1","typeGuard":null,"tryCatchPattern":"if resolved, esc, reason, err := checkGHRun(gate); err != nil && strings.Contains(err.Error(), \"failed to query workflow runs\") {\n    // log wrapped cause: fmt.Errorf(\"%w\", err); retry after backoff\n}","preventionTips":["Keep gh authenticated and tokens rotated","Pin workflow names to actual workflow filenames","Test the gh command manually before wiring it into a gate","Add retry with backoff around gate evaluation"],"tags":["github-actions","gh-cli","error-wrapping"],"backgroundTag":"gh-cli-command-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}