gastownhall/beads · critical

configured storage backend %q in metadata.json is not recogn

Error message

configured storage backend %q in metadata.json is not recognized and cannot be opened as Dolt; %s

What it means

Opening a DoltStore was refused because metadata.json contains a backend identifier that is not recognized at all — neither supported (dolt) nor a known removed backend. Beads fails closed rather than opening a new empty Dolt database over unknown data.

Source

Thrown at internal/storage/dolt/open.go:90

// unconditional.
func ApplyResolvedServerPort(beadsDir string, cfg *Config) {
	resolved := doltserver.DefaultConfig(beadsDir)
	cfg.ServerPort = resolved.Port
	cfg.ServerPortSource = resolved.PortSource
	cfg.ServerPortSharedServer = resolved.PortSharedServer
}

// requireDoltBackend keeps metadata-driven callers from bypassing the storage
// factory and interpreting another backend's workspace as Dolt. Removed backend
// identifiers deliberately remain recognizable in metadata so this check can fail
// closed instead of opening a new, empty Dolt database.
func requireDoltBackend(fileCfg *configfile.Config) error {
	switch fileCfg.Backend {
	case configfile.BackendPostgres, configfile.BackendMySQL, configfile.BackendSQLite:
		return fmt.Errorf("configured storage backend %q is no longer supported and cannot be opened as Dolt: %s", fileCfg.Backend, configfile.RemovedBackendDetail(fileCfg.Backend))
	}
	if !configfile.IsSupportedBackend(fileCfg.Backend) {
		return fmt.Errorf("configured storage backend %q in metadata.json is not recognized and cannot be opened as Dolt; %s", fileCfg.Backend, configfile.BackendNotOpenedGuarantee)
	}
	backend := fileCfg.GetBackend()
	if backend != configfile.BackendDolt {
		return fmt.Errorf("configured storage backend %q cannot be opened as Dolt", backend)
	}
	return nil
}

// NewFromConfig creates a DoltStore based on the metadata.json configuration.
// beadsDir is the path to the .beads directory.
func NewFromConfig(ctx context.Context, beadsDir string) (*DoltStore, error) {
	return NewFromConfigWithOptions(ctx, beadsDir, nil)
}

// NewFromConfigWithCLIOptions creates a DoltStore using the standalone CLI
// auto-start policy from cmd/bd/main.go. This is for CLI helper paths like
// `bd doctor` that should behave the same way as normal top-level CLI commands
// while still honoring externally managed server mode.

View on GitHub (pinned to 71377f2769)

Solutions

  1. Verify metadata.json contents and fix the backend value to "dolt" if the data is actually Dolt
  2. Confirm you are pointing at the intended .beads directory
  3. Check beads version compatibility if the directory was written by another tool/version
  4. Restore metadata.json from git or backup if it was corrupted

Example fix

// before: typo in metadata.json
{"backend": "doltt"}

// after
{"backend": "dolt"}
Defensive patterns

Strategy: validation

Validate before calling

// Validate backend identifier before opening
cfg, _ := configfile.Load(beadsDir)
if !configfile.IsSupportedBackend(cfg.Backend) {
    return fmt.Errorf("metadata.json has unrecognized backend %q", cfg.Backend)
}

Try / catch

store, err := dolt.NewFromConfigWithOptions(beadsDir, opts)
if err != nil && strings.Contains(err.Error(), "not recognized") {
    // inspect/repair metadata.json, restore from git or backup
    return repairMetadata(beadsDir)
}

Prevention

When it happens

Trigger: Calling NewFromConfigWithOptions / NewFromConfigWithCLIOptions when fileCfg.Backend fails configfile.IsSupportedBackend (typo, empty string, future/unknown identifier).

Common situations: Hand-edited or corrupted metadata.json; .beads directory produced by a newer or third-party build; empty backend field after a failed write.

Related errors


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