gastownhall/beads · error

no storage backend is open

Error message

no storage backend is open

What it means

doltBackupSize reports the size of the active Dolt database through the globally-open store instance. If the package-level `store` variable is nil — no storage backend has been opened for this process — it returns the error 'no storage backend is open'. This guards against calling the sizer interface (ActiveDatabaseSizer) on a nil store, which would panic.

Source

Thrown at cmd/bd/backup_dolt.go:363

	result["backup_url"] = cfg.BackupURL
	result["backup_name"] = cfg.BackupName
	result["created_at"] = cfg.CreatedAt.Format(time.RFC3339)

	state, err := loadDoltBackupState()
	if err == nil && state != nil {
		result["last_sync"] = state.LastSync.Format(time.RFC3339)
		result["sync_duration"] = state.Duration
	}

	return result
}

// doltBackupSize returns the active database size when the current store
// instance can measure its storage locally. Unsupported backends preserve the
// optional status-field contract instead of failing the command.
func doltBackupSize(ctx context.Context) (int64, bool, error) {
	if store == nil {
		return 0, false, fmt.Errorf("no storage backend is open")
	}
	return doltBackupSizeForStore(ctx, store)
}

func doltBackupSizeForStore(ctx context.Context, candidate storage.DoltStorage) (int64, bool, error) {
	sizer, ok := storage.UnwrapStore(candidate).(storage.ActiveDatabaseSizer)
	if !ok {
		return 0, false, nil
	}
	return doltBackupSizeFromSizer(ctx, sizer)
}

func doltBackupSizeFromSizer(ctx context.Context, sizer storage.ActiveDatabaseSizer) (int64, bool, error) {
	size, err := sizer.ActiveDatabaseSize(ctx)
	if err != nil {
		var unsupported *storage.ErrUnsupported
		if errors.As(err, &unsupported) {
			return 0, false, nil

View on GitHub (pinned to 71377f2769)

Solutions

  1. Ensure the bd command opens the database (routes through the normal command bootstrap) before requesting backup size
  2. If calling internals from tests, initialize the global store (or use doltBackupSizeForStore with a real storage.DoltStorage) before calling doltBackupSize
  3. Check for recent code changes that bypassed the store-open step

Example fix

// before
count, hasSize, err := doltBackupSize(ctx) // store is nil
// after
ensureStoreOpen(ctx) // or construct store first
if store == nil {
    return fmt.Errorf("open the database before requesting backup size")
}
count, hasSize, err := doltBackupSize(ctx)
Defensive patterns

Strategy: type-guard

Validate before calling

if store == nil {
    // open the store or skip size reporting before calling doltBackupSize
    return 0, false, errors.New("open the storage backend first")
}

Type guard

func storeOpen(s storage.DoltStorage) bool { return s != nil }
// call site:
if !storeOpen(store) { /* initialize or skip */ }

Try / catch

size, ok, err := doltBackupSize(ctx)
if err != nil {
    if strings.Contains(err.Error(), "no storage backend is open") {
        // degrade gracefully: omit size from status output
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Invoking bd backup commands that query database size (e.g. `bd backup` status paths calling doltBackupSize) when `store` was never initialized via bd's database-open (ensureStore/open) path, e.g. running with flags that skip DB opening or before the daemon/router opens the store.

Common situations: Backup subcommands run in contexts where the DB was not opened first (scripted misuse of internal helpers, tests that forgot store setup), or a code regression where the store-open step was skipped before sizing.

Related errors


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