jlcodes99/cockpit-tools · error

PROVIDER_BASE_URL_EXISTS

PROVIDER_BASE_URL_EXISTS

Error message

PROVIDER_BASE_URL_EXISTS

What it means

createCodexModelProvider rejects a new provider whose baseUrl normalizes to the same value as an existing provider. The service enforces uniqueness of provider base URLs by comparing normalizeCodexModelProviderBaseUrl(item.baseUrl) across all stored providers. It is a deliberate duplicate-prevention guard, not a network or runtime failure.

Source

Thrown at src/services/codexModelProviderService.ts:589

  boundInstanceId?: string;
  website?: string;
  apiKeyUrl?: string;
  wireApi?: CodexProviderWireApi;
  supportsWebsockets?: boolean;
  enableModePreference?: CodexProviderEnableModePreference;
  integrationType?: 'sub2api' | 'new_api';
  boundOauthAccountId?: string | null;
  initialApiKey?: string;
  initialApiKeyName?: string;
}): Promise<CodexModelProvider> {
  const name = sanitizeName(input.name);
  const baseUrl = normalizeBaseUrlForStore(input.baseUrl);
  const normalizedBaseUrl = normalizeCodexModelProviderBaseUrl(baseUrl);
  if (!name) throw new Error('PROVIDER_NAME_REQUIRED');
  if (!normalizedBaseUrl) throw new Error('PROVIDER_BASE_URL_INVALID');
  const providers = await ensureProvidersLoaded();
  if (providers.some((item) => normalizeCodexModelProviderBaseUrl(item.baseUrl) === normalizedBaseUrl)) {
    throw new Error('PROVIDER_BASE_URL_EXISTS');
  }
  const now = Date.now();
  const wireApi = normalizeWireApi(input.wireApi);
  const provider: CodexModelProvider = {
    id: createProviderId(),
    name,
    baseUrl,
    sourceTag: sanitizeName(input.sourceTag ?? '') || undefined,
    integrationType: normalizeIntegrationType(input.integrationType),
    modelCatalog:
      normalizeModelCatalog(input.modelCatalog) ??
      presetModelCatalogForBaseUrl(baseUrl),
    modelContextWindows: normalizeModelContextWindows(
      input.modelContextWindows,
      normalizeModelCatalog(input.modelCatalog) ??
        presetModelCatalogForBaseUrl(baseUrl) ??
        [],
    ),

View on GitHub (pinned to 1ed8b77992)

Solutions

  1. Search existing providers for one whose baseUrl matches (after normalization) and reuse/update it via updateCodexModelProvider instead of creating a new one.
  2. Change the new provider's baseUrl to a distinct endpoint (different host, port, or path prefix).
  3. If the old duplicate is stale, delete it first, then re-run createCodexModelProvider.
  4. Wrap the call in try/catch for 'PROVIDER_BASE_URL_EXISTS' and fall back to an update path when the message matches.

Example fix

// before: blind create, throws on second run
await createCodexModelProvider({ name: 'proxy', baseUrl: 'http://localhost:8080/v1' });
// after: reuse or update the existing provider
const existing = (await listCodexModelProviders()).find(
  (p) => normalizeCodexModelProviderBaseUrl(p.baseUrl) === normalizeCodexModelProviderBaseUrl('http://localhost:8080/v1'),
);
const provider = existing
  ? await updateCodexModelProvider(existing.id, { name: 'proxy' })
  : await createCodexModelProvider({ name: 'proxy', baseUrl: 'http://localhost:8080/v1' });
Defensive patterns

Strategy: validation

Validate before calling

import { listCodexModelProviders } from './codexModelProviderService';
// approximate normalizer: compare trimmed, lower-cased URL without trailing slash
const norm = (u: string) => new URL(u).toString().replace(/\/$/, '').toLowerCase();
const normalized = norm(baseUrl);
const exists = (await listCodexModelProviders()).some((p) => norm(p.baseUrl) === normalized);
if (exists) throw new Error('PROVIDER_BASE_URL_EXISTS');

Try / catch

try {
  await createCodexModelProvider({ name, baseUrl });
} catch (e) {
  if ((e as Error).message === 'PROVIDER_BASE_URL_EXISTS') {
    // fall back to locating and updating the existing provider
  } else throw e;
}

Prevention

When it happens

Trigger: Calling createCodexModelProvider({ name, baseUrl, ... }) when any already-stored provider's baseUrl, after normalization (scheme/host/path canonicalization), equals the normalized form of the incoming baseUrl. Thrown at src/services/codexModelProviderService.ts:589 before any provider record is created.

Common situations: Re-running an init/import script that already created the provider; adding a second provider entry pointing at the same gateway (e.g. http://localhost:8080 vs localhost:8080/v1, which normalize to the same value); switching a proxy to a new port but leaving the old provider row in place; UI double-submit of the save form (handleSaveProvider).

Related errors


AI-assisted analysis of jlcodes99/cockpit-tools@1ed8b77992 (2026-09-05). Data as JSON: /api/errors/c4342ed8509ebdc0. Report an issue: GitHub.