{"record":{"id":"5025e10b3f2457c9","repo":"plandex-ai/plandex","slug":"has-duplicates","errorCode":null,"errorMessage":"Has duplicates: ","messagePattern":"Has duplicates: ","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"app/server/handlers/models.go","lineNumber":63,"sourceCode":"\tif len(modelsInput.CustomModels) > 0 {\n\t\tif os.Getenv(\"IS_CLOUD\") != \"\" {\n\t\t\tapiOrg, err := getApiOrg(auth.OrgId)\n\t\t\tif err != nil {\n\t\t\t\tlog.Printf(\"Error fetching org: %v\\n\", err)\n\t\t\t\thttp.Error(w, \"Failed to create custom model: \"+err.Error(), http.StatusInternalServerError)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif apiOrg.IntegratedModelsMode {\n\t\t\t\thttp.Error(w, \"Custom models are not supported on Plandex Cloud in Integrated Models mode\", http.StatusBadRequest)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\thasDuplicates, errMsg := modelsInput.CheckNoDuplicates()\n\tif !hasDuplicates {\n\t\thttp.Error(w, \"Has duplicates: \"+errMsg, http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tfor _, provider := range modelsInput.CustomProviders {\n\t\tif provider.Name == \"\" {\n\t\t\tmsg := \"Provider name is required\"\n\t\t\tlog.Println(msg)\n\t\t\thttp.Error(w, msg, http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t}\n\n\tfor _, model := range modelsInput.CustomModels {\n\t\tif model.ModelId == \"\" {\n\t\t\tmsg := \"Model id is required\"\n\t\t\tlog.Println(msg)\n\t\t\thttp.Error(w, msg, http.StatusBadRequest)\n\t\t\treturn","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/models.go#L45-L81","documentation":"The handler runs ModelsInput.CheckNoDuplicates() to ensure no duplicate model ids, provider names, or model pack names appear in the payload. If duplicates are found, CheckNoDuplicates returns false plus a descriptive message, and the server responds HTTP 400 with \"Has duplicates: \" + that message. Note the inverted-looking condition: !hasDuplicates means the check failed.","triggerScenarios":"POSTing a ModelsInput where the same custom model id, provider name, or model pack name appears more than once across CustomProviders, CustomModels, or CustomModelPacks arrays.","commonSituations":"Merging two exported models.json files without deduplicating; scripted configs that append rather than replace entries; copy-pasting a model block to tweak it and forgetting to remove the original.","solutions":["Read the text after \"Has duplicates: \" to see exactly which name/id is duplicated","Deduplicate entries by id/name in your config before applying","Call CheckNoDuplicates() on the ModelsInput client-side to catch this before the request","If merging configs, key entries by id/name and overwrite instead of appending"],"exampleFix":"// before\ncustomModels: [\n  {modelId: \"my-gpt\", ...},\n  {modelId: \"my-gpt\", ...}\n]\n// after\ncustomModels: [\n  {modelId: \"my-gpt\", ...}\n]","handlingStrategy":"validation","validationCode":"ok, errMsg := input.CheckNoDuplicates()\nif !ok {\n    return fmt.Errorf(\"duplicate in models input: %s\", errMsg)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always call CheckNoDuplicates on ModelsInput before submitting","Key merged config entries by id/name so duplicates overwrite instead of accumulate","Run a linter over models.json that flags repeated modelId/provider/pack names"],"tags":["http","go","validation","bad-request","duplicate-entries"],"backgroundTag":"duplicate-entry-validation","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}