can1357/oh-my-pi · error · Error

Marketplace "${entry.name}" already exists

Error message

Marketplace "${entry.name}" already exists

What it means

addMarketplaceEntry() is a pure registry transform that enforces unique marketplace names. If the registry already contains a marketplace with the same name, it throws instead of silently overwriting the existing entry (which would lose the old source/catalogPath). Callers are expected to remove or update the entry explicitly.

Source

Thrown at packages/coding-agent/src/extensibility/plugins/marketplace/registry.ts:136

		// Accept any numeric version — forward compatible reads
		return { ...data, version: 2 };
	} catch (err) {
		if (isEnoent(err)) return emptyInstalledPluginsRegistry();
		throw err;
	}
}

export async function writeInstalledPluginsRegistry(filePath: string, reg: InstalledPluginsRegistry): Promise<void> {
	await atomicWriteJson(filePath, reg);
}

// ── Marketplace CRUD ─────────────────────────────────────────────────
// Pure functions that transform registry state. Caller is responsible for
// reading, mutating, and writing back.

export function addMarketplaceEntry(reg: MarketplacesRegistry, entry: MarketplaceRegistryEntry): MarketplacesRegistry {
	if (reg.marketplaces.some(m => m.name === entry.name)) {
		throw new Error(`Marketplace "${entry.name}" already exists`);
	}
	return { ...reg, marketplaces: [...reg.marketplaces, entry] };
}

export function removeMarketplaceEntry(reg: MarketplacesRegistry, name: string): MarketplacesRegistry {
	const filtered = reg.marketplaces.filter(m => m.name !== name);
	if (filtered.length === reg.marketplaces.length) {
		throw new Error(`Marketplace "${name}" not found`);
	}
	return { ...reg, marketplaces: filtered };
}

export function getMarketplaceEntry(reg: MarketplacesRegistry, name: string): MarketplaceRegistryEntry | undefined {
	return reg.marketplaces.find(m => m.name === name);
}

// ── Installed plugin CRUD ────────────────────────────────────────────

View on GitHub (pinned to 9690622007)

Solutions

  1. Check existence first with getMarketplaceEntry() and skip or replace the entry
  2. Remove the existing marketplace (removeMarketplaceEntry) then re-add with the desired source
  3. Use an update flow that mutates the existing entry in place instead of appending
  4. Choose a different marketplace name if both sources are wanted

Example fix

// before
reg = addMarketplaceEntry(reg, entry); // throws if exists
// after
if (!getMarketplaceEntry(reg, entry.name)) {
  reg = addMarketplaceEntry(reg, entry);
} else {
  reg = removeMarketplaceEntry(reg, entry.name);
  reg = addMarketplaceEntry(reg, entry);
}
Defensive patterns

Strategy: validation

Validate before calling

import { getMarketplaceEntry, addMarketplaceEntry, removeMarketplaceEntry } from './registry';
if (getMarketplaceEntry(reg, entry.name)) {
  reg = removeMarketplaceEntry(reg, entry.name);
}
reg = addMarketplaceEntry(reg, entry);

Type guard

null

Try / catch

try {
  reg = addMarketplaceEntry(reg, entry);
} catch (err) {
  if (err.message === `Marketplace "${entry.name}" already exists`) {
    reg = removeMarketplaceEntry(reg, entry.name);
    reg = addMarketplaceEntry(reg, entry); // replace
  } else throw err;
}

Prevention

When it happens

Trigger: Calling addMarketplaceEntry() with a name already present in reg.marketplaces — e.g. re-running a "marketplace add" for an existing marketplace, or an update flow that adds instead of replacing.

Common situations: Re-running a setup script that adds marketplaces idempotently but does not check existence; adding a marketplace whose name collides with a previously registered one from a different source; a partially-failed update that left the entry in place.

Related errors


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