Skip to content

handle_noop_message: transient search failure falls through to create and can produce duplicate [aw] No-Op Runs issues #19606

@samuelkahessay

Description

@samuelkahessay

Context

Observed while running gh-aw v0.52.1 in production in samuelkahessay/prd-to-prod — a parallel agentic pipeline with concurrent agent work. Still present on current main at 6502173c8 (v0.53.1-2-g6502173c8).

Location

actions/setup/js/handle_noop_message.cjs — lines 24–63, ensureAgentRunsIssue()

Problem

The search for an existing [aw] No-Op Runs issue catches errors and falls through to the create path without distinguishing "search returned zero results" from "search threw an error":

// Lines 24-41
try {
  const { data } = await github.rest.search.issuesAndPullRequests({
    q: searchQuery,
    per_page: 1,
  });

  if (data.total_count > 0) {
    // ... return existing issue
  }
} catch (error) {
  core.warning(`Error searching for no-op runs issue: ${getErrorMessage(error)}`);
}

// Falls through to create on BOTH "not found" AND "search failed"
const { data: newIssue } = await github.rest.issues.create({ ... });

A transient API failure (rate limit, network blip) can create a duplicate [aw] No-Op Runs tracking issue when one already exists. Over time this fragments the no-op run history across multiple issues.

The caller already expects ensureAgentRunsIssue() to throw and abort posting if issue setup fails (main() lines 133–138), so treating a search failure as "not found" is the wrong behavior here.

Proposed fix

Distinguish between "search returned zero results" and "search threw an error." On search error, either retry or propagate a search-specific error rather than falling through to create:

let existingIssue = null;
try {
  const { data } = await github.rest.search.issuesAndPullRequests({ ... });
  if (data.total_count > 0) {
    existingIssue = data.items[0];
  }
} catch (error) {
  throw new Error(
    `Failed to search for existing no-op runs issue: ${getErrorMessage(error)}`
  );
}

if (existingIssue) {
  return { number: existingIssue.number, node_id: existingIssue.node_id };
}

// Only create if search succeeded and returned zero results

Environment

  • Observed in production: v0.52.1
  • Still present on: main at 6502173c8 (v0.53.1-2-g6502173c8)
  • Pipeline: Parallel agentic workflow (decompose → dispatch → implement → review → merge)
  • Repo: samuelkahessay/prd-to-prod

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions