{"record":{"id":"935cdb0fbd1736d8","repo":"Billionmail/BillionMail","slug":"supplier-already-exists","errorCode":null,"errorMessage":"supplier already exists","messagePattern":"supplier already exists","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/askai/supplier.go","lineNumber":599,"sourceCode":"\texistingModels := GetModelList(supplierName)\n\n\t// Update the model status\n\tfor i, model := range existingModels {\n\t\tif model.ModelId == modelId {\n\t\t\texistingModels[i].Status = status\n\t\t\treturn saveModelsToFile(modelsFile, existingModels)\n\t\t}\n\t}\n\n\treturn errors.New(\"model not found\")\n}\n\n// AddSupplier creates a new supplier configuration file with the provided details.\n// It checks if a supplier with the same name already exists, and if not, it creates a new Supplier struct\nfunc AddSupplier(supplierTitle string, supplierName string, baseUrl string, apiKey string) error {\n\tsupplierPath := SUPPLIER_CONFIG_PATH + \"/\" + supplierName\n\tif public.FileExists(supplierPath) {\n\t\treturn errors.New(\"supplier already exists\")\n\t}\n\n\tsupplier := Supplier{\n\t\tSupplierTitle:   supplierTitle,\n\t\tSupplierName:    supplierName,\n\t\tBaseUrl:         baseUrl,\n\t\tBaseUrlExample:  baseUrl,\n\t\tIsUseUrlExample: false,\n\t\tApiKey:          apiKey,\n\t\tHome:            \"\",\n\t\tHelp:            \"\",\n\t\tStatus:          true,\n\t\tSort:            100, // Default sort order, can be changed later\n\t\tIcon:            \"\",  // Default icon, can be set later\n\t}\n\n\treturn SaveSupplierConfig(supplierName, supplier)\n}","sourceCodeStart":581,"sourceCodeEnd":617,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/askai/supplier.go#L581-L617","documentation":"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.","triggerScenarios":"Calling AddSupplier with a supplierName whose config directory already exists — e.g. re-adding a built-in supplier or retrying an earlier successful AddSupplier.","commonSituations":"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.","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"],"exampleFix":"// before\nerr := AddSupplier(\"OpenAI\", \"openai\", url, key) // -> \"supplier already exists\"\n\n// after\nif !public.FileExists(SUPPLIER_CONFIG_PATH + \"/openai\") {\n    err := AddSupplier(\"OpenAI\", \"openai\", url, key)\n}","handlingStrategy":"validation","validationCode":"supplierPath := SUPPLIER_CONFIG_PATH + \"/\" + supplierName\nif public.FileExists(supplierPath) {\n    // supplier already present — update instead of add\n    return updateSupplierConfig(supplierName, baseUrl, apiKey)\n}\nreturn AddSupplier(title, supplierName, baseUrl, apiKey)","typeGuard":null,"tryCatchPattern":"if err := AddSupplier(title, name, url, key); err != nil {\n    if strings.Contains(err.Error(), \"already exists\") {\n        // treat as success or update existing config\n    } else { return err }\n}","preventionTips":["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"],"tags":["configuration","duplicate","ai-supplier"],"backgroundTag":"resource-already-exists","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}