gastownhall/beads · error

persisting sanitized database name to metadata.json: %w

Error message

persisting sanitized database name to metadata.json: %w

What it means

migrateHyphenatedDB renames a hyphenated Dolt database directory and rewrites metadata.json (GH#3231). If cfg.Save(beadsDir) fails while persisting the sanitized dolt_database name, the error is wrapped so the migration failure is attributed to the metadata write, not the rename.

Source

Thrown at cmd/bd/store_factory.go:220

		_, newErr := os.Stat(newDir)
		switch {
		case newErr == nil:
			return fmt.Errorf("cannot auto-migrate database: both %q and %q exist under %s; remove one manually and retry",
				oldName, newName, dataDir)
		case !os.IsNotExist(newErr):
			return fmt.Errorf("checking target directory %q: %w", newDir, newErr)
		default:
			if err := os.Rename(oldDir, newDir); err != nil {
				return fmt.Errorf("renaming database directory: %w", err)
			}
			fmt.Fprintf(os.Stderr, "bd: migrated database directory %q → %q (GH#3231)\n", oldName, newName)
		}
	}

	if cfg != nil && cfg.DoltDatabase != newName {
		cfg.DoltDatabase = newName
		if err := cfg.Save(beadsDir); err != nil {
			return fmt.Errorf("persisting sanitized database name to metadata.json: %w", err)
		}
		fmt.Fprintf(os.Stderr, "bd: updated metadata.json dolt_database %q → %q (GH#3231)\n", oldName, newName)
	}
	return nil
}

// newReadOnlyStoreFromConfig creates a read-only storage backend from the beads
// directory's persisted metadata.json configuration.
//
// For embedded mode, invalid characters (hyphens, dots) are sanitized in-memory
// only — no directory renames or metadata.json writes. This prevents cross-repo
// hydration from mutating foreign projects (GH#3231).
func newReadOnlyStoreFromConfig(ctx context.Context, beadsDir string) (storage.DoltStorage, error) {
	return openNonMutatingStoreFromConfig(ctx, beadsDir, false)
}

// newPreviewStoreFromConfig is newReadOnlyStoreFromConfig for a preview
// command (--dry-run, --inspect) reading a repository it was only pointed at:

View on GitHub (pinned to 71377f2769)

Solutions

  1. Check write permission on .beads/metadata.json and the beads dir for the running user.
  2. Free disk space / check quota if Save failed on write.
  3. Manually update dolt_database in metadata.json to the sanitized (underscore) name to match the renamed directory.
  4. Retry the operation after fixing the environment; the rename is idempotent once metadata matches.

Example fix

// after manual repair:
# metadata.json
"dolt_database": "my_project_db"   # was "my-project-db"; directory already renamed
Defensive patterns

Strategy: try-catch

Validate before calling

mdPath := filepath.Join(beadsDir, "metadata.json")
if info, err := os.Stat(mdPath); err != nil || info.Mode().Perm()&0200 == 0 {
    // cannot persist sanitized name; fix permissions first
}

Try / catch

if err := migrateHyphenatedDB(beadsDir, oldName, newName, cfg); err != nil {
    if strings.Contains(err.Error(), "persisting sanitized database name") {
        // fix metadata.json writability, align dolt_database manually, retry
    }
    return err
}

Prevention

When it happens

Trigger: During newDoltStoreFromConfig, when the configured DoltDatabase contains hyphens, the directory rename succeeds, but writing the updated metadata.json fails (read-only beads dir, permission denied, disk full, corrupt config file state).

Common situations: Read-only mount of the .beads directory; running bd under a user without write permission to metadata.json; disk quota exhaustion; concurrent processes holding conflicting writes.

Related errors


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