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

  1. Check public.FileExists(SUPPLIER_CONFIG_PATH+"/"+supplierName) before calling AddSupplier
  2. If the supplier exists but needs different credentials, update the existing config instead of re-adding
  3. 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

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


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/935cdb0fbd1736d8. Report an issue: GitHub.