{"record":{"id":"f827f714b40751e8","repo":"alibaba/open-code-review","slug":"provider-q-already-exists","errorCode":null,"errorMessage":"provider %q already exists","messagePattern":"provider %q already exists","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/opencodereview/provider_tui.go","lineNumber":1381,"sourceCode":"\t// Optional fields are always applied so users can intentionally clear them.\n\t// To detect \"user cleared the API key\" vs \"user left it masked/untouched\",\n\t// apiKey is only overwritten when the user actively typed something.\n\tentry.URL = r.url\n\tentry.Protocol = r.protocol\n\tentry.AuthHeader = r.authHeader\n\tif key, edited := m.customAPIKeyForSave(); edited {\n\t\tentry.APIKey = key\n\t}\n\t// Switching an entry to an ambient protocol drops the key it no longer uses,\n\t// rather than leaving a live credential in a file nothing reads it from.\n\tif entry.Protocol == llm.ProtocolAnthropicBedrock {\n\t\tentry.APIKey = \"\"\n\t}\n\t// If name changed, delete old key\n\tif r.editTargetName != \"\" && r.editTargetName != r.provider {\n\t\tif _, exists := m.existingCfg.CustomProviders[r.provider]; exists {\n\t\t\tm.formError = fmt.Sprintf(`Provider \"%s\" already exists`, r.provider)\n\t\t\treturn fmt.Errorf(\"provider %q already exists\", r.provider)\n\t\t}\n\t\tdelete(m.existingCfg.CustomProviders, r.editTargetName)\n\t\tif m.existingCfg.Provider == r.editTargetName {\n\t\t\tm.existingCfg.Provider = r.provider\n\t\t\tm.existingCfg.Model = \"\"\n\t\t}\n\t}\n\tm.existingCfg.CustomProviders[r.provider] = entry\n\n\tif err := saveConfig(m.configPath, m.existingCfg); err != nil {\n\t\tm.formError = fmt.Sprintf(\"failed to save: %v\", err)\n\t\tif reloaded, reloadErr := loadOrCreateConfig(m.configPath); reloadErr == nil {\n\t\t\tm.existingCfg = reloaded\n\t\t\tm.customProviders = collectCustomProviders(reloaded)\n\t\t} else {\n\t\t\tm.existingCfg.CustomProviders = backupProviders\n\t\t\tm.existingCfg.Provider = backupActiveProvider\n\t\t\tm.existingCfg.Model = backupActiveModel","sourceCodeStart":1363,"sourceCodeEnd":1399,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/cmd/opencodereview/provider_tui.go#L1363-L1399","documentation":"When saving an edited or newly created custom provider, the chosen provider name collides with an existing entry that is not the one being edited. Since custom providers are keyed by name, allowing the save would silently overwrite the other provider's settings, so the save is rejected with the conflicting name quoted.","triggerScenarios":"Thrown at cmd/opencodereview/provider_tui.go:1381 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Choose a different provider name; the name collides with an existing entry in the config","If you meant to modify the existing provider, use the edit flow instead of the add flow","Check existing entries (including built-in provider names) before adding a custom provider"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}