gastownhall/beads · error

db: DependencySQLRepository.WispSourceIDs: %w

Error message

db: DependencySQLRepository.WispSourceIDs: %w

What it means

WispSourceIDs calls issueops.WispIDSetInTx to classify which of the given IDs live in the wisp plane, in one scoped query. Like the delete/count paths, a missing wisps table inside WispIDSetInTx is treated as 'no wisps' rather than an error, so this wrapper means a genuine failure occurred: SQL error, connection loss, or scan failure.

Source

Thrown at internal/storage/domain/db/dependency.go:959

	}
	graph := make(map[string][]string)
	if err := issueops.AppendSchedulingGraphInTx(ctx, r.runner, []string{"dependencies"}, graph); err != nil {
		return "", fmt.Errorf("db: DependencySQLRepository.CycleThroughEdges: %w", err)
	}
	if err := issueops.AppendSchedulingGraphInTx(ctx, r.runner, []string{"wisp_dependencies"}, graph); err != nil && !dberrors.IsTableNotExist(err) {
		return "", fmt.Errorf("db: DependencySQLRepository.CycleThroughEdges (wisps): %w", err)
	}
	return issueops.CycleThroughEdgesInGraph(graph, edges), nil
}

// WispSourceIDs classifies a batch of ids by plane in one scoped query. It is
// the proxied twin of the in-tx probe the store-backed dependency editor runs,
// and shares its implementation so the two answer the same question — down to
// treating a missing wisps table as "no wisps" rather than an error.
func (r *dependencySQLRepositoryImpl) WispSourceIDs(ctx context.Context, ids []string) (map[string]struct{}, error) {
	set, err := issueops.WispIDSetInTx(ctx, r.runner, ids)
	if err != nil {
		return nil, fmt.Errorf("db: DependencySQLRepository.WispSourceIDs: %w", err)
	}
	return set, nil
}

func (r *dependencySQLRepositoryImpl) GetDependencyRecordsForIssues(ctx context.Context, issueIDs []string) (map[string][]*types.Dependency, error) {
	if len(issueIDs) == 0 {
		return map[string][]*types.Dependency{}, nil
	}
	out, err := issueops.GetDependencyRecordsForIssuesInTx(ctx, r.runner, issueIDs)
	if err != nil {
		return nil, fmt.Errorf("db: DependencySQLRepository.GetDependencyRecordsForIssues: %w", err)
	}
	return out, nil
}

func (r *dependencySQLRepositoryImpl) GetWispDependencyRecordsForIDs(ctx context.Context, wispIDs []string) (map[string][]*types.Dependency, error) {
	if len(wispIDs) == 0 {
		return map[string][]*types.Dependency{}, nil

View on GitHub (pinned to 71377f2769)

Solutions

  1. Unwrap to see the root driver/SQL error.
  2. Verify wisp tables exist and are healthy (run migrations/repair).
  3. Retry transient failures with a fresh context.
  4. Ensure IDs are valid non-empty strings; empty input short-circuits at the caller, not here.

Example fix

// before
set, err := repo.WispSourceIDs(ctx, ids)
if err != nil { panic(err) }
// after: degrade gracefully when wisps are unavailable
set, err := repo.WispSourceIDs(ctx, ids)
if err != nil {
    log.Warn("wisp probe failed, assuming none", "err", err)
    set = map[string]struct{}{}
}
Defensive patterns

Strategy: fallback

Validate before calling

if len(ids) == 0 {
    return map[string]struct{}{} // skip the DB probe entirely
}

Type guard

func emptyIDs(ids []string) bool { return len(ids) == 0 }

Try / catch

set, err := repo.WispSourceIDs(ctx, ids)
if err != nil {
    // degrade: assume no wisps rather than failing the edit
    log.Warn("wisp classification failed", "err", err)
    set = map[string]struct{}{}
}

Prevention

When it happens

Trigger: Calling WispSourceIDs(ctx, ids) with a non-empty ID list where WispIDSetInTx errors other than missing-table: corrupted wisp tables, driver failure, context cancellation.

Common situations: Dependency editors deciding whether an ID is a wisp before editing, against an unhealthy database; permission errors on wisp tables; timeouts under heavy load.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


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