Billionmail/BillionMail · error
Cannot delete the system's built-in model supplier.
Error message
Cannot delete the system's built-in model supplier.
What it means
RemoveSupplier refuses to delete a supplier whose name also exists under SUPPLIER_TEMPLATE_PATH, because such suppliers are system built-ins shipped with the application. Deleting them would break default functionality and they would be restored on upgrade anyway.
Source
Thrown at core/internal/service/askai/supplier.go:630
Sort: 100, // Default sort order, can be changed later
Icon: "", // Default icon, can be set later
}
return SaveSupplierConfig(supplierName, supplier)
}
// RemoveSupplier deletes a supplier's configuration directory and all its contents.
// It checks if the supplier exists, and if so, it removes the directory and its files
// If the supplier does not exist, it returns an error indicating that the supplier cannot be found.
// This function is useful for cleaning up unused suppliers from the configuration.
func RemoveSupplier(supplierName string) error {
supplierPath := SUPPLIER_CONFIG_PATH + "/" + supplierName
if !public.FileExists(supplierPath) {
return errors.New("supplier does not exist")
}
templatePath := SUPPLIER_TEMPLATE_PATH + "/" + supplierName
if public.FileExists(templatePath) {
return errors.New("Cannot delete the system's built-in model supplier.")
}
err := os.RemoveAll(supplierPath)
if err != nil {
return err
}
return nil
}
// SetModelTitle updates the title of a model in the supplier's models.json file.
// It reads the existing models, modifies the title of the specified model, and saves the updated list back to the file.
// If the model is not found, it returns an error indicating that the model does not exist.
func SetModelTitle(supplierName string, modelId string, title string) error {
modelsFile := SUPPLIER_CONFIG_PATH + "/" + supplierName + "/models.json"
if !public.FileExists(modelsFile) {
return errors.New("models file does not exist for supplier: " + supplierName)
}View on GitHub (pinned to fc36c76c05)
Solutions
- Only remove custom suppliers — list SUPPLIER_CONFIG_PATH entries that have no counterpart in SUPPLIER_TEMPLATE_PATH and skip built-ins
- If the goal is to disable a built-in supplier, call SetSupplierStatus(name, false) instead of deleting it
- If credentials must change, overwrite the built-in's config (SaveSupplierConfig) rather than removing it
Example fix
// before
for _, s := range allSuppliers {
RemoveSupplier(s) // fails on built-ins
}
// after
for _, s := range allSuppliers {
if !public.FileExists(SUPPLIER_TEMPLATE_PATH+"/"+s) {
RemoveSupplier(s)
} else {
SetSupplierStatus(s, false) // disable built-ins instead
}
} Defensive patterns
Strategy: validation
Validate before calling
func isBuiltinSupplier(name string) bool {
return public.FileExists(SUPPLIER_TEMPLATE_PATH + "/" + name)
}
// only delete customs:
if !isBuiltinSupplier(name) { RemoveSupplier(name) } Try / catch
if err := RemoveSupplier(name); err != nil {
if strings.Contains(err.Error(), "built-in") {
// disable instead: SetSupplierStatus(name, false)
} else { return err }
} Prevention
- Filter out names present under SUPPLIER_TEMPLATE_PATH in bulk-delete jobs
- Prefer SetSupplierStatus(false) over deletion for built-ins
- Never assume every config dir is user-created
When it happens
Trigger: Calling RemoveSupplier on any built-in supplier (one that has a directory under SUPPLIER_TEMPLATE_PATH), even though its config directory exists.
Common situations: Trying to clean up 'unused' suppliers that are actually default built-ins; scripting bulk deletion of all suppliers; users wanting to reset a built-in supplier's credentials.
Related errors
- supplier does not exist
- supplier configuration is incomplete, cannot set status
- model not found
- supplier already exists
- models file does not exist for supplier:
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/a169e6e26bcbcc1a.
Report an issue: GitHub.