gastownhall/beads · error
count wisp labels: %w
Error message
count wisp labels: %w
What it means
DeleteResolvedSetInTx aborts when it cannot count rows in the "wisp_labels" table for the wisp IDs in the resolved set. This wraps the driver-level error returned by CountRowsForIssueIDsInTx. The count contributes to the labels figure of the delete result.
Source
Thrown at internal/storage/issueops/delete.go:226
}
var depsCount, labelsCount, eventsCount int
var err error
if depsCount, err = CountRowsForIssueIDsInTx(ctx, tx, "dependencies", set.RegularIDs); err != nil {
return nil, fmt.Errorf("count dependencies: %w", err)
}
wispDepsCount, err := CountRowsForIssueIDsInTx(ctx, tx, "wisp_dependencies", set.WispIDs)
if err != nil {
return nil, fmt.Errorf("count wisp dependencies: %w", err)
}
depsCount += wispDepsCount
if labelsCount, err = CountRowsForIssueIDsInTx(ctx, tx, "labels", set.RegularIDs); err != nil {
return nil, fmt.Errorf("count labels: %w", err)
}
wispLabelsCount, err := CountRowsForIssueIDsInTx(ctx, tx, "wisp_labels", set.WispIDs)
if err != nil {
return nil, fmt.Errorf("count wisp labels: %w", err)
}
labelsCount += wispLabelsCount
if eventsCount, err = CountRowsForIssueIDsInTx(ctx, tx, "events", set.RegularIDs); err != nil {
return nil, fmt.Errorf("count events: %w", err)
}
wispEventsCount, err := CountRowsForIssueIDsInTx(ctx, tx, "wisp_events", set.WispIDs)
if err != nil {
return nil, fmt.Errorf("count wisp events: %w", err)
}
eventsCount += wispEventsCount
for i := 0; i < len(set.All); i += deleteBatchSize {
end := i + deleteBatchSize
if end > len(set.All) {
end = len(set.All)
}
batch := set.All[i:end]View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped driver error to distinguish missing table from connection failure.
- Run schema migrations / ensure the backend supports wisp tables.
- Retry on a fresh transaction if the cause is transient.
- Check database server logs around the failure time.
Example fix
// before
if err != nil {
return err
}
// after
if err != nil {
var missing tableMissingError
if errors.As(err, &missing) {
return fmt.Errorf("run 'bd migrate' first: %w", err)
}
return err
} Defensive patterns
Strategy: validation
Validate before calling
// confirm wisp support before calling delete on wisps
rows, err := db.QueryContext(ctx,
`SELECT table_name FROM information_schema.tables WHERE table_name = 'wisp_labels'`)
if err != nil || !rows.Next() {
return errors.New("wisp_labels missing: migrate schema or use a wisp-capable backend")
} Try / catch
res, err := store.DeleteInTx(ctx, tx, ids)
if err != nil && strings.Contains(err.Error(), "wisp_labels") {
return fmt.Errorf("backend lacks wisp support or schema is stale: %w", err)
} Prevention
- Verify the storage backend supports wisp tables (see storage boundary docs).
- Run migrations after every beads version upgrade.
- Probe information_schema for wisp tables once at startup.
When it happens
Trigger: Calling DeleteInTx/DeleteIssuesInTx where wisp_labels is absent (pre-wisp schema or driver that doesn't create wisp tables), corrupted, or the connection fails between the labels count and this query.
Common situations: Embedded-mode or older storage backend lacking wisp_labels; Dolt schema drift after a version upgrade; transient I/O error on the database file/server.
Related errors
- count wisp events: %w
- count wisp dependencies: %w
- count labels: %w
- count events: %w
- failed to begin transaction: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/1b6bb4495033541a.
Report an issue: GitHub.