gastownhall/beads · error

loading config: %w

Error message

loading config: %w

What it means

guardLegacyUpgradeWorkspace loads the workspace config via configfile.LoadForDiscovery and wraps any load failure as "loading config: %w". Called before any upgrade/guard decision (doctor validation, legacy workspace discovery), it protects against unreadable or malformed config in the .beads directory. The root cause (parse error, IO error, schema error) is preserved in the chain.

Source

Thrown at cmd/bd/legacy_upgrade_guard.go:31

	"github.com/steveyegge/beads/internal/doltserver"
	"github.com/steveyegge/beads/internal/git"
	"github.com/steveyegge/beads/internal/storage/embeddeddolt"
	"github.com/steveyegge/beads/internal/utils"
	"golang.org/x/mod/semver"
)

// guardLegacyUpgradeWorkspace rejects the reviewed pre-Dolt and legacy-Dolt
// workspace shapes before command setup can track a version, migrate metadata,
// or construct a store. It intentionally classifies only metadata, regular
// SQLite files, and the bounded local version witness; storage internals stay
// behind the driver boundary.
func guardLegacyUpgradeWorkspace(beadsDir string) error {
	if beadsDir == "" {
		return nil
	}
	cfg, err := configfile.LoadForDiscovery(beadsDir)
	if err != nil {
		return fmt.Errorf("loading config: %w", err)
	}
	if isHistoricalSQLiteWorkspace(beadsDir, cfg) {
		return legacyUpgradeRefusal("historical SQLite workspace")
	}
	// Validate read-only discovery metadata before any caller can use Load,
	// which migrates legacy config.json to metadata.json. Removed and unknown
	// backends must fail without changing the only pointer to their data.
	if err := validateConfiguredBackend(cfg); err != nil {
		return err
	}
	serverMode := cfg != nil && strings.EqualFold(cfg.DoltMode, configfile.DoltModeServer)
	if embeddeddolt.HasRepository(beadsDir) && !serverMode {
		return nil
	}
	version, present := legacyUpgradeVersionWitness(beadsDir)
	if serverMode && present && legacyServerVersion(version) {
		return legacyUpgradeRefusal(fmt.Sprintf("legacy Dolt server workspace from bd %s", version))
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped root cause — usually a JSON parse or file permission error naming the config file
  2. Validate/repair the JSON in .beads/metadata.json (or legacy config.json); restore from git if the workspace is tracked
  3. Check file permissions/ownership of the .beads directory
  4. If migrating from legacy SQLite, back up .beads and let the upgrade tooling regenerate config

Example fix

// before (malformed)
{"database": "beads.db",,}
// after
{"database": "beads.db"}
Defensive patterns

Strategy: validation

Validate before calling

// pre-validate workspace config JSON before running guarded commands
python3 -m json.tool .beads/metadata.json > /dev/null || echo "config JSON is malformed"

Try / catch

if err := guardLegacyUpgradeWorkspace(beadsDir); err != nil {
    var perr *json.SyntaxError
    if errors.As(err, &perr) { /* repair JSON at perr.Offset */ }
    return err
}

Prevention

When it happens

Trigger: Running bd commands that hit guardLegacyUpgradeWorkspace (doctor workspace validation, upgrade guards) in a workspace whose config.json/metadata.json cannot be loaded — malformed JSON, unreadable file, or discovery-time validation failure.

Common situations: Hand-edited config.json with JSON syntax errors; .beads directory with wrong permissions; partially migrated workspace mixing legacy and new config files; interrupted upgrade leaving truncated metadata.json.

Related errors


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