gastownhall/beads · error

gate not found: %s

Error message

gate not found: %s

What it means

Thrown inside the gate AddWaiter transaction when GetIssue reports the gate ID does not exist. The caller asked to attach a waiter to a gate issue, but no issue with that ID is present in storage. This distinguishes a clean not-found from a storage failure (which produces 'reading gate %s' instead).

Source

Thrown at cmd/bd/gate_proxied_server.go:250

	defer func() {
		if c := metrics.Global(); c != nil {
			c.CloseEventAndAdd(evt)
		}
	}()

	gateID := args[0]
	waiter := args[1]

	if uowProvider == nil {
		return HandleError("proxied-server UOW provider not initialized")
	}

	applied, err := uow.RunTxResult(ctx, uowProvider, func(ctx context.Context, uw uow.UnitOfWork) (gateAddWaiterApply, string, error) {
		var out gateAddWaiterApply

		issue, err := uw.IssueUseCase().GetIssue(ctx, gateID)
		if gateProxiedNotFound(err) {
			return out, "", fmt.Errorf("gate not found: %s", gateID)
		}
		if err != nil {
			return out, "", fmt.Errorf("reading gate %s: %w", gateID, err)
		}
		if issue.IssueType != "gate" {
			return out, "", fmt.Errorf("%s is not a gate issue (type=%s)", gateID, issue.IssueType)
		}

		for _, w := range issue.Waiters {
			if w == waiter {
				out.already = true
				// Empty commit message: a registered waiter is a no-op, and a
				// no-op writes no Dolt commit.
				return out, "", nil
			}
		}

		newWaiters := append(issue.Waiters, waiter)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run `bd show <gateID>` to confirm the issue exists in the connected database
  2. Check for typos in the gate ID; use `bd list --type gate` to list valid gate issues
  3. If the gate was deleted intentionally, remove or recreate the waiter registration instead of retrying
  4. Verify the server is pointed at the expected database/remote (`bd doctor`)

Example fix

// before: blind AddWaiter call
err := client.AddWaiter(ctx, gateID, waiter)
// after: confirm the gate exists and is a gate first
issue, err := client.Show(ctx, gateID)
if err != nil || issue == nil {
    return fmt.Errorf("gate %s does not exist; run bd list --type gate", gateID)
}
if issue.IssueType != "gate" {
    return fmt.Errorf("%s is not a gate issue (type=%s)", gateID, issue.IssueType)
}
err = client.AddWaiter(ctx, gateID, waiter)
Defensive patterns

Strategy: validation

Validate before calling

issue, err := bdClient.Show(ctx, gateID)
if err != nil {
    return fmt.Errorf("gate %s does not exist in this database; run bd list --type gate", gateID)
}

Type guard

func gateExists(ctx context.Context, uc *IssueUseCase, gateID string) bool {
    issue, err := uc.GetIssue(ctx, gateID)
    return err == nil && issue != nil
}

Try / catch

err := client.AddWaiter(ctx, gateID, waiter)
if err != nil && strings.Contains(err.Error(), "gate not found") {
    gates, _ := client.List(ctx, ListFilter{IssueType: "gate"})
    return fmt.Errorf("gate %s not found; known gates: %v", gateID, gates)
}

Prevention

When it happens

Trigger: Calling the proxied-server gate AddWaiter path with a gateID that was never created, was deleted, or is mistyped; gateProxiedNotFound(err) returns true for the GetIssue result.

Common situations: Typo in the gate issue ID (bd-xxx vs bd-yyy); gate deleted after a workflow run completed; issue created in a different database/remote than the one the server is connected to; stale cached ID from an earlier session.

Related errors


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