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

  1. Inspect the wrapped cause; restore storage connectivity or restart the Dolt server
  2. Run `bd doctor`/migrations if the wisp tables are corrupt or partially migrated
  3. Retry the operation; transient cancellation/timeouts usually clear
  4. 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

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


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