gastownhall/beads · error
wisp plane membership: %w
Error message
wisp plane membership: %w
What it means
This error wraps a failure from `IssueUseCase().GetWispsByIDs(ctx, ids)` inside WispPlaneIDs, which determines which of the given IDs are members of the wisp (closed/tombstoned) plane. A missing-table condition returns (nil, nil) — an empty set — by design; this error is only returned for real storage failures, aborting the operation.
Source
Thrown at cmd/bd/export_source.go:335
}
return rel, nil
}
// WispPlaneIDs classifies by wisps-table membership through the plane-pinned
// GetWispsByIDs read (row flags are NOT a substitute — see the exportSource
// interface comment). A rig without the wisp tables has no wisp-plane rows,
// mirroring the tolerance of the wisp-plane legs in LoadExportRelations.
func (s *uowExportSource) WispPlaneIDs(ctx context.Context, ids []string) (map[string]bool, error) {
if len(ids) == 0 {
return nil, nil
}
wisps, err := s.uw.IssueUseCase().GetWispsByIDs(ctx, ids)
if err != nil {
if dberrors.IsTableNotExist(err) {
return nil, nil
}
return nil, fmt.Errorf("wisp plane membership: %w", err)
}
set := make(map[string]bool, len(wisps))
for _, w := range wisps {
set[w.ID] = true
}
return set, nil
}
// mergeExportMap copies src entries into dst. The label/comment planes are
// disjoint by ID (an issue lives in exactly one of issues/wisps), so a plain
// overwrite-merge reassembles the classic partitioned loaders' single map.
func mergeExportMap[V any](dst, src map[string]V) {
for k, v := range src {
dst[k] = v
}
}
View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped cause; restore storage connectivity or restart the Dolt server
- Run `bd doctor`/migrations if the wisp tables are corrupt or partially migrated
- Retry the operation; transient cancellation/timeouts usually clear
- If the driver's table-not-exist error isn't being recognized, upgrade so legacy rigs correctly resolve to an empty wisp set
Defensive patterns
Strategy: try-catch
Validate before calling
// no cheap pre-check; probe backend reachability before wisp-plane lookups
if err := store.PingContext(ctx); err != nil {
return fmt.Errorf("storage backend unreachable: %w", err)
} Type guard
func isTableNotExist(err error) bool { return dberrors.IsTableNotExist(err) } Try / catch
set, err := WispPlaneIDs(ctx, ids)
if err != nil {
return fmt.Errorf("wisp plane membership: %w", err)
} Prevention
- Treat an empty result as legitimate for legacy rigs (missing tables return nil, nil)
- Keep wisp tables healthy via migrations/`bd doctor` before wisp-aware operations
- Use adequate context timeouts for large ID batches
- Diagnose from the wrapped cause, not the wrapper message
When it happens
Trigger: Calling WispPlaneIDs when GetWispsByIDs fails with a non-table-not-exist error: Dolt backend unreachable, SQL error filtering wisps by ID batch, cancelled context, or corrupt wisp/issue table.
Common situations: Export or compaction flows that consult wisp membership on a database whose wisp tables exist but are broken; Dolt server outage during a wisp-aware operation; timeouts on large ID batches.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- load wisp labels: %w
- load wisp comments: %w
- load wisp comment counts: %w
- load dependency records: %w
- load wisp dependency counts: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/d7b9e84564a4c90f.
Report an issue: GitHub.