gastownhall/beads · error

storage backend does not support backup operations

Error message

storage backend does not support backup operations

What it means

runBackupExport requires the unwrapped store to implement storage.BackupStore. storage.UnwrapStore(store) peels proxy/wrapper layers, and if the concrete backend does not implement BackupDatabase, backup cannot proceed. The Dolt backend supports backups; simpler backends (e.g. JSON-file storage) do not.

Source

Thrown at cmd/bd/backup_export.go:152

	if err != nil {
		return nil, err
	}

	// Change detection: skip if nothing changed (unless forced)
	if !force {
		currentCommit, err := store.GetCurrentCommit(ctx)
		if err != nil {
			return nil, fmt.Errorf("failed to get current commit: %w", err)
		}
		if currentCommit == state.LastDoltCommit && state.LastDoltCommit != "" {
			debug.Logf("backup: no changes since last backup (commit %s)\n", truncateHash(currentCommit))
			return state, nil
		}
	}

	bs, ok := storage.UnwrapStore(store).(storage.BackupStore)
	if !ok {
		return nil, fmt.Errorf("storage backend does not support backup operations")
	}

	if err := bs.BackupDatabase(ctx, dir); err != nil {
		// Persist the attempt time even on failure so the throttle
		// interval (checked by maybeAutoBackup via state.Timestamp)
		// applies to the next command. Without this, a sync that keeps
		// failing — e.g. a slow/overloaded shared Dolt server — retries
		// on EVERY bd command instead of once per interval, turning a
		// transient slowdown into a self-amplifying storm (the 2026-07
		// shared-dolt CPU-pin incident). LastDoltCommit is deliberately
		// left unchanged so change-detection still sees pending work and
		// a real backup runs once the failure clears.
		state.Timestamp = time.Now().UTC()
		if saveErr := saveBackupState(dir, state); saveErr != nil {
			debug.Logf("backup: failed to persist throttle state after error: %v\n", saveErr)
		}
		return nil, err
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check your storage backend (bd doctor or presence of .beads/dolt/) — backups require Dolt storage.
  2. Migrate the workspace to Dolt storage if on legacy JSON (follow bd's migration/import path), then retry.
  3. Skip auto-backup expectations for non-Dolt backends: back up the storage files yourself (e.g. copy .beads/issues.jsonl).
  4. If you believe your backend should support backups, verify you're on a recent bd version and file an issue.

Example fix

// check backend
ls .beads/dolt 2>/dev/null && echo dolt || echo non-dolt
// non-dolt fallback
# disable/ignore auto-backup and back up storage files manually
cp -f .beads/issues.jsonl ~/backups/issues-$(date +%F).jsonl
Defensive patterns

Strategy: type-guard

Validate before calling

// confirm Dolt-backed storage before attempting backup flows
if _, err := os.Stat(".beads/dolt"); err != nil {
    log.Println("workspace is not Dolt-backed; BackupStore operations unavailable")
}

Type guard

bs, ok := storage.UnwrapStore(store).(storage.BackupStore)
if !ok {
    // backend does not support backups; skip auto-backup instead of erroring
    return nil
}

Try / catch

if err := maybeAutoBackup(ctx, store, dir); err != nil {
    if strings.Contains(err.Error(), "does not support backup operations") {
        log.Println("non-Dolt backend: skipping built-in backup; back up storage files manually")
        return nil
    }
    return err
}

Prevention

When it happens

Trigger: Auto-backup (maybeAutoBackup) or backup export runs against a storage backend that lacks BackupDatabase — i.e., the workspace is not using Dolt storage.

Common situations: Legacy workspace still on JSON issue storage (.beads/issues.jsonl) instead of Dolt; custom/embedded storage drivers without backup support; mismatched bd build using a reduced backend.

Related errors


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