gastownhall/beads · error

GetIssuesByIDs: %w

Error message

GetIssuesByIDs: %w

What it means

tryIncrementalExport fetches the issues it needs to upsert via store.GetIssuesByIDs. If the store lookup fails, the incremental path aborts with this wrapped error (and the caller, maybeAutoExport, falls back to a full export). It indicates a storage-layer failure, not a git/file problem.

Source

Thrown at cmd/bd/export_auto.go:1098

			return 0, 0, nil, false, err
		}
		return issueCount, memoryCount, changed.Upserted, true, nil
	}
	if total > incrementalExportThreshold {
		debug.Logf("auto-export: %d changes exceeds threshold %d; full export\n",
			total, incrementalExportThreshold)
		return 0, 0, nil, false, nil
	}

	// Fetch fresh data for upserted IDs (including anything carried over
	// from last cycle) and apply the same template/infra/owner filters the
	// full export uses.
	var records map[string][]byte
	droppedByFilter := make(map[string]bool)
	if len(upsertIDs) > 0 {
		issues, fetchErr := store.GetIssuesByIDs(ctx, upsertIDs)
		if fetchErr != nil {
			return 0, 0, nil, false, fmt.Errorf("GetIssuesByIDs: %w", fetchErr)
		}
		infraSet := store.GetInfraTypes(ctx)
		// Owner-exclusion safety net, mirroring exportToFile's: without
		// this, a config-excluded owner's issue that changes would leak
		// into the git-committed JSONL via the incremental path even
		// though the full-export path always excludes it (be-shbed).
		ownerExcludes := buildOwnerExcludeSet(ctx, storeExportSource{}, nil)
		filtered := make([]*types.Issue, 0, len(issues))
		for _, iss := range issues {
			// Record IDs that GetIssuesByIDs returned but we deliberately
			// filtered out. Those DO need dropping from the export because
			// the full-export path excludes them; leaving a stale record
			// in place would diverge the two outputs.
			if iss.IsTemplate {
				droppedByFilter[iss.ID] = true
				continue
			}
			if len(infraSet) > 0 && infraSet[string(iss.IssueType)] {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Retry the sync — maybeAutoExport falls back to a full export path which may succeed
  2. Check the local store health (`bd doctor`) for corruption or lock issues
  3. Close competing bd processes holding the database, then rerun `bd sync`

Example fix

// before
// GetIssuesByIDs: database is locked
// after
bd doctor   # verify store health
bd sync     # retries, falling back to full export if needed
Defensive patterns

Strategy: fallback

Validate before calling

// Check store responsiveness before incremental export
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if _, err := store.GetIssuesByIDs(ctx, []string{"smoke-test-id"}); err != nil && !errors.Is(err, ErrNotFound) {
    fmt.Println("store unhealthy; prefer full export / bd doctor")
}

Try / catch

count, _, _, _, err := tryIncrementalExport(...)
if err != nil && strings.Contains(err.Error(), "GetIssuesByIDs:") {
    // Fall back to a full export, which rebuilds from a fresh store read
    fullExport()
}

Prevention

When it happens

Trigger: tryIncrementalExport calls store.GetIssuesByIDs(ctx, upsertIDs) for non-empty upsertIDs and the store returns an error — DB corruption, locked/closed database, driver failure.

Common situations: Dolt/database locked by another process; corrupted local store; storage driver errors; transient DB issues during rapid successive bd commands.

Related errors


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