chatboxai/chatbox · error · Error

builtin-provider-id-conflict

Error message

builtin-provider-id-conflict

What it means

Thrown by assertCustomProviderIdIsAvailable when importing/parsing a custom provider config whose id collides with a builtin provider id (isBuiltinProviderId returns true). The guard runs inside parseProviderConfig for any entry with isCustom === true, before the custom provider is registered, preventing builtin ids from being shadowed or overwritten.

Source

Thrown at src/renderer/utils/provider-config.ts:53

      docs: z.string().optional(),
      models: z.string().optional(),
    })
    .optional(),
  settings: z.object({
    apiHost: z.string(),
    apiPath: z.string().optional(),
    apiKey: z.string().optional(),
    models: z.array(modelInfoSchema).optional(),
  }),
})

const ProviderConfigSchema = z.union([BuiltinProviderConfigSchema, CustomProviderConfigSchema])

export type ProviderConfig = z.infer<typeof ProviderConfigSchema>

function assertCustomProviderIdIsAvailable(providerId: string): void {
  if (isBuiltinProviderId(providerId)) {
    throw new Error(CUSTOM_PROVIDER_ID_CONFLICT)
  }
}

function parseProviderConfig(json: unknown): ProviderInfo | (ProviderSettings & { id: ModelProviderEnum }) | undefined {
  if (json && typeof json === 'object' && 'isCustom' in json && json.isCustom === true) {
    const parsedCustom = CustomProviderConfigSchema.parse(json)
    assertCustomProviderIdIsAvailable(parsedCustom.id)
    const providerType =
      parsedCustom.type === 'openai'
        ? ModelProviderType.OpenAI
        : parsedCustom.type === 'openai-responses'
          ? ModelProviderType.OpenAIResponses
          : ModelProviderType.Claude

    const providerInfo: ProviderInfo = {
      id: parsedCustom.id,
      name: parsedCustom.name,
      type: providerType,

View on GitHub (pinned to 81571269ad)

Solutions

  1. Rename the custom provider's id to something non-builtin (e.g. prefix with a namespace: 'myorg-openai') before importing.
  2. If you intend to override a builtin, use the builtin override mechanism (settings edit) rather than importing a custom entry with the same id.
  3. Audit the JSON being imported: check the 'id' field of each isCustom:true entry against the builtin id list.
  4. Improve the error to include the colliding id so the user knows which entry to rename.

Example fix

// before
function assertCustomProviderIdIsAvailable(providerId: string): void {
  if (isBuiltinProviderId(providerId)) {
    throw new Error(CUSTOM_PROVIDER_ID_CONFLICT)
  }
}
// after — name the colliding id in the message
function assertCustomProviderIdIsAvailable(providerId: string): void {
  if (isBuiltinProviderId(providerId)) {
    throw new Error(`${CUSTOM_PROVIDER_ID_CONFLICT}: '${providerId}' is reserved`)
  }
}
Defensive patterns

Strategy: validation

Validate before calling

// Validate a custom-provider config import before passing to parseProviderConfig.
function assertCustomProviderImportSafe(json: unknown, isBuiltin: (id: string) => boolean): void {
  if (json && typeof json === 'object' && (json as any).isCustom === true) {
    const id = (json as any).id
    if (typeof id === 'string' && isBuiltin(id)) {
      throw new Error(`Rename custom provider id '${id}' — it collides with a builtin.`)
    }
  }
}

Type guard

function isCustomProviderConfig(v: unknown): v is { isCustom: true; id: string } {
  return typeof v === 'object' && v !== null &&
    (v as any).isCustom === true && typeof (v as any).id === 'string'
}

Try / catch

try {
  registerProvider(parseProviderConfig(json))
} catch (e) {
  if (e instanceof Error && e.message === CUSTOM_PROVIDER_ID_CONFLICT) {
    promptUserToRenameProvider(json.id)
    return
  }
  throw e
}

Prevention

When it happens

Trigger: parseProviderConfig receives a JSON object with isCustom:true and an id that isBuiltinProviderId recognizes (e.g. 'openai', 'anthropic', 'chatbox-ai'). The custom config is rejected wholesale via CUSTOM_PROVIDER_ID_CONFLICT before any field is read.

Common situations: User imports a shared provider JSON whose author reused a builtin id; migrating a config between app versions where a previously-custom id became builtin; copy-paste of a builtin provider's exported JSON with isCustom flipped; third-party provider packs that don't namespace their ids.

Related errors


AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12). Data as JSON: /api/errors/9ce82f5e887024b0. Report an issue: GitHub.