gastownhall/beads · error

descendants: wisp_dependencies probe: %w

Error message

descendants: wisp_dependencies probe: %w

What it means

Wraps a failure from optionalTableExists probing the wisp_dependencies table during GetDescendants. The probe runs 'SELECT 1 FROM wisp_dependencies LIMIT 1' and only treats table-not-exist as a clean 'false'; any other probe error (connection, permissions, driver malfunction) is wrapped here and aborts the descendants walk. This decides whether wisp dependencies can be traversed.

Source

Thrown at internal/storage/domain/db/issue_descendants.go:51

		snippet: fmt.Sprintf(" AND %s.id IN (SELECT id FROM %s)", alias, cteName),
		args:    args,
	}
}

func (r *issueSQLRepositoryImpl) GetDescendants(ctx context.Context, rootID string, filter types.IssueFilter) ([]*types.Issue, error) {
	levelFilter := filter
	levelFilter.ParentID = nil
	levelFilter.Limit = 0
	levelFilter.Offset = 0

	issueWhereClauses, issueArgs, err := buildIssueFilterClauses("", levelFilter, issuesFilterTables)
	if err != nil {
		return nil, fmt.Errorf("descendants: issues filter: %w", err)
	}

	wispDepsExist, err := r.optionalTableExists(ctx, "wisp_dependencies")
	if err != nil {
		return nil, fmt.Errorf("descendants: wisp_dependencies probe: %w", err)
	}
	walkWisps := wispDepsExist && !filter.SkipWisps
	if walkWisps {
		empty, probeErr := r.wispsTableEmptyOrMissing(ctx)
		if probeErr != nil {
			return nil, fmt.Errorf("descendants: wisps table probe: %w", probeErr)
		}
		walkWisps = !empty
	}

	var wispWhereClauses []string
	var wispArgs []any
	if walkWisps {
		wispWhereClauses, wispArgs, err = buildIssueFilterClauses("", levelFilter, wispsFilterTables)
		if err != nil {
			return nil, fmt.Errorf("descendants: wisps filter: %w", err)
		}
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped cause; if it's a permissions error, grant SELECT on wisp_dependencies or fix the connection user.
  2. Upgrade the storage/dberrors layer if the server's table-not-exist error shape isn't recognized (falls through as a hard error).
  3. Check connectivity and retry — the probe is read-only and cheap.
  4. If wisps are unused in your deployment, set filter.SkipWisps to bypass wisp traversal entirely.

Example fix

// before
deps, err := repo.GetDescendants(ctx, id, filter) // hard-fails on probe error
// after
filter.SkipWisps = true // deployment has no wisp tables / no perms
deps, err := repo.GetDescendants(ctx, id, filter)
Defensive patterns

Strategy: fallback

Validate before calling

// pre-probe permissions with the same identity the app uses
rows, err := db.Query("SELECT 1 FROM wisp_dependencies LIMIT 1")
if err != nil && !isTableNotExist(err) { log.Printf("wisp probe unhealthy: %v", err) }
if rows != nil { rows.Close() }

Try / catch

deps, err := repo.GetDescendants(ctx, id, filter)
if err != nil {
    if strings.Contains(err.Error(), "wisp_dependencies probe") {
        filter.SkipWisps = true // degrade: walk issues only
        return repo.GetDescendants(ctx, id, filter)
    }
    return err
}

Prevention

When it happens

Trigger: Calling GetDescendants when the wisp_dependencies probe fails with something other than sql.ErrNoRows or a recognized table-not-exist error: connection failure, permission denied on the table, corrupted catalog, or context cancellation.

Common situations: DB user lacking SELECT on wisp_dependencies, connection dropped between queries, a Dolt server version whose not-exist error isn't recognized by dberrors.IsTableNotExist (version drift), or cancellation timeouts.

Related errors


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