Billionmail/BillionMail · error
supplier already exists
Error message
supplier already exists
What it means
AddSupplier creates a new supplier config directory, but first checks whether SUPPLIER_CONFIG_PATH/<supplierName> already exists. If it does, creation is refused to avoid overwriting existing supplier settings and models.
Source
Thrown at core/internal/service/askai/supplier.go:599
existingModels := GetModelList(supplierName)
// Update the model status
for i, model := range existingModels {
if model.ModelId == modelId {
existingModels[i].Status = status
return saveModelsToFile(modelsFile, existingModels)
}
}
return errors.New("model not found")
}
// AddSupplier creates a new supplier configuration file with the provided details.
// It checks if a supplier with the same name already exists, and if not, it creates a new Supplier struct
func AddSupplier(supplierTitle string, supplierName string, baseUrl string, apiKey string) error {
supplierPath := SUPPLIER_CONFIG_PATH + "/" + supplierName
if public.FileExists(supplierPath) {
return errors.New("supplier already exists")
}
supplier := Supplier{
SupplierTitle: supplierTitle,
SupplierName: supplierName,
BaseUrl: baseUrl,
BaseUrlExample: baseUrl,
IsUseUrlExample: false,
ApiKey: apiKey,
Home: "",
Help: "",
Status: true,
Sort: 100, // Default sort order, can be changed later
Icon: "", // Default icon, can be set later
}
return SaveSupplierConfig(supplierName, supplier)
}View on GitHub (pinned to fc36c76c05)
Solutions
- Check public.FileExists(SUPPLIER_CONFIG_PATH+"/"+supplierName) before calling AddSupplier
- If the supplier exists but needs different credentials, update the existing config instead of re-adding
- Choose a different unique supplierName
Example fix
// before
err := AddSupplier("OpenAI", "openai", url, key) // -> "supplier already exists"
// after
if !public.FileExists(SUPPLIER_CONFIG_PATH + "/openai") {
err := AddSupplier("OpenAI", "openai", url, key)
} Defensive patterns
Strategy: validation
Validate before calling
supplierPath := SUPPLIER_CONFIG_PATH + "/" + supplierName
if public.FileExists(supplierPath) {
// supplier already present — update instead of add
return updateSupplierConfig(supplierName, baseUrl, apiKey)
}
return AddSupplier(title, supplierName, baseUrl, apiKey) Try / catch
if err := AddSupplier(title, name, url, key); err != nil {
if strings.Contains(err.Error(), "already exists") {
// treat as success or update existing config
} else { return err }
} Prevention
- Check existence before add; make add flows idempotent
- Normalize supplier names (trim/lowercase) before use
- Keep a registry of known supplier names to avoid duplicates
When it happens
Trigger: Calling AddSupplier with a supplierName whose config directory already exists — e.g. re-adding a built-in supplier or retrying an earlier successful AddSupplier.
Common situations: Duplicate registration attempts after a first add that the caller didn't realize succeeded; a supplier name colliding with a built-in template supplier; name normalization differences (case/whitespace) making the caller think the name is new.
Related errors
- supplier configuration is incomplete, cannot set status
- model not found
- supplier does not exist
- Cannot delete the system's built-in model supplier.
- models file does not exist for supplier:
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/935cdb0fbd1736d8.
Report an issue: GitHub.