can1357/oh-my-pi · error · ValueError

Bank '${newName}' already exists

Error message

Bank '${newName}' already exists

What it means

`renameBank()` refuses to rename onto an existing bank: if a directory for `newName` already exists under `banks/`, the rename would overwrite another bank's database, so it fails fast.

Source

Thrown at packages/mnemopi/src/core/banks.ts:75

		}
		return banks.sort();
	}
	bankExists(name: string): boolean {
		if (name === "default") return true;
		return existsSync(join(this.banksDir, name));
	}
	getBankDbPath(name: string): string {
		if (name.length === 0 || name === "default") return join(this.dataDir, DB_FILENAME);
		this.validateName(name);
		return join(this.banksDir, name, DB_FILENAME);
	}
	renameBank(oldName: string, newName: string): string {
		if (oldName === "default") throw new ValueError("Cannot rename 'default' bank");
		this.validateName(newName);
		const oldDir = join(this.banksDir, oldName);
		const newDir = join(this.banksDir, newName);
		if (!existsSync(oldDir)) throw new ValueError(`Bank '${oldName}' does not exist`);
		if (existsSync(newDir)) throw new ValueError(`Bank '${newName}' already exists`);
		renameSync(oldDir, newDir);
		return join(newDir, DB_FILENAME);
	}
	getBankStats(name: string): BankStats {
		const dbPath = this.getBankDbPath(name);
		const present = existsSync(dbPath);
		const size = present ? statSync(dbPath).size : 0;
		return { name, exists: present, db_path: dbPath, dbSizeBytes: size, db_size_bytes: size };
	}
	private validateName(name: string): void {
		if (name.length === 0) throw new ValueError("Bank name cannot be empty");
		if (name === "default") return;
		if (name.length > 64) throw new ValueError(`Bank name '${name}' exceeds 64 characters`);
		for (let i = 0; i < name.length; i++) {
			const code = name.charCodeAt(i);
			const ok =
				(code >= 48 && code <= 57) ||
				(code >= 65 && code <= 90) ||

View on GitHub (pinned to 9690622007)

Solutions

  1. Pick a unique `newName` (check `listBanks()`/`getBankStats(newName).exists` first).
  2. Delete or rename away the existing target bank first if it is disposable.
  3. Append a suffix to guarantee uniqueness.
  4. Catch the ValueError and choose a different target name.

Example fix

// before
banks.renameBank("tmp", "work");
// after
let target = "work";
while (banks.getBankStats(target).exists) target = `work-${Date.now()}`;
banks.renameBank("tmp", target);
Defensive patterns

Strategy: validation

Validate before calling

if (banks.getBankStats(newName).exists) {
  throw new Error(`Target bank '${newName}' already exists`);
}

Type guard

null

Try / catch

try {
  banks.renameBank(oldName, newName);
} catch (err) {
  if (err instanceof ValueError && err.message.includes("already exists")) {
    newName = `${newName}-${Date.now()}`;
    banks.renameBank(oldName, newName);
  } else throw err;
}

Prevention

When it happens

Trigger: Calling `renameBank(oldName, newName)` where `<dataDir>/banks/<newName>/` exists — target name collides with an existing bank.

Common situations: Rename loops that pick names already in use, renaming to a name auto-derived from a project that has its own bank, retried scripts after a partial previous run.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/746eebdf6917ddfd. Report an issue: GitHub.