{"record":{"id":"9ce82f5e887024b0","repo":"chatboxai/chatbox","slug":"builtin-provider-id-conflict","errorCode":null,"errorMessage":"builtin-provider-id-conflict","messagePattern":"builtin-provider-id-conflict","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/renderer/utils/provider-config.ts","lineNumber":53,"sourceCode":"      docs: z.string().optional(),\n      models: z.string().optional(),\n    })\n    .optional(),\n  settings: z.object({\n    apiHost: z.string(),\n    apiPath: z.string().optional(),\n    apiKey: z.string().optional(),\n    models: z.array(modelInfoSchema).optional(),\n  }),\n})\n\nconst ProviderConfigSchema = z.union([BuiltinProviderConfigSchema, CustomProviderConfigSchema])\n\nexport type ProviderConfig = z.infer<typeof ProviderConfigSchema>\n\nfunction assertCustomProviderIdIsAvailable(providerId: string): void {\n  if (isBuiltinProviderId(providerId)) {\n    throw new Error(CUSTOM_PROVIDER_ID_CONFLICT)\n  }\n}\n\nfunction parseProviderConfig(json: unknown): ProviderInfo | (ProviderSettings & { id: ModelProviderEnum }) | undefined {\n  if (json && typeof json === 'object' && 'isCustom' in json && json.isCustom === true) {\n    const parsedCustom = CustomProviderConfigSchema.parse(json)\n    assertCustomProviderIdIsAvailable(parsedCustom.id)\n    const providerType =\n      parsedCustom.type === 'openai'\n        ? ModelProviderType.OpenAI\n        : parsedCustom.type === 'openai-responses'\n          ? ModelProviderType.OpenAIResponses\n          : ModelProviderType.Claude\n\n    const providerInfo: ProviderInfo = {\n      id: parsedCustom.id,\n      name: parsedCustom.name,\n      type: providerType,","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/utils/provider-config.ts#L35-L71","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Rename the custom provider's id to something non-builtin (e.g. prefix with a namespace: 'myorg-openai') before importing.","If you intend to override a builtin, use the builtin override mechanism (settings edit) rather than importing a custom entry with the same id.","Audit the JSON being imported: check the 'id' field of each isCustom:true entry against the builtin id list.","Improve the error to include the colliding id so the user knows which entry to rename."],"exampleFix":"// before\nfunction assertCustomProviderIdIsAvailable(providerId: string): void {\n  if (isBuiltinProviderId(providerId)) {\n    throw new Error(CUSTOM_PROVIDER_ID_CONFLICT)\n  }\n}\n// after — name the colliding id in the message\nfunction assertCustomProviderIdIsAvailable(providerId: string): void {\n  if (isBuiltinProviderId(providerId)) {\n    throw new Error(`${CUSTOM_PROVIDER_ID_CONFLICT}: '${providerId}' is reserved`)\n  }\n}","handlingStrategy":"validation","validationCode":"// Validate a custom-provider config import before passing to parseProviderConfig.\nfunction assertCustomProviderImportSafe(json: unknown, isBuiltin: (id: string) => boolean): void {\n  if (json && typeof json === 'object' && (json as any).isCustom === true) {\n    const id = (json as any).id\n    if (typeof id === 'string' && isBuiltin(id)) {\n      throw new Error(`Rename custom provider id '${id}' — it collides with a builtin.`)\n    }\n  }\n}","typeGuard":"function isCustomProviderConfig(v: unknown): v is { isCustom: true; id: string } {\n  return typeof v === 'object' && v !== null &&\n    (v as any).isCustom === true && typeof (v as any).id === 'string'\n}","tryCatchPattern":"try {\n  registerProvider(parseProviderConfig(json))\n} catch (e) {\n  if (e instanceof Error && e.message === CUSTOM_PROVIDER_ID_CONFLICT) {\n    promptUserToRenameProvider(json.id)\n    return\n  }\n  throw e\n}","preventionTips":["Namespace custom provider ids (e.g. 'myorg-<name>') when generating config exports.","Run import configs through a validator that lists collisions with builtin ids before registration.","Improve the error to include the colliding id for faster remediation."],"tags":["provider-config","validation","import","id-conflict"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}