{"record":{"id":"d418fd380f7f51d9","repo":"alibaba/open-code-review","slug":"model-is-required-for-manual-configuration","errorCode":null,"errorMessage":"model is required for manual configuration","messagePattern":"model is required for manual configuration","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/opencodereview/provider_cmd.go","lineNumber":108,"sourceCode":"\tfor _, m := range toRemove {\n\t\tremoveSet[m] = struct{}{}\n\t}\n\tresult := make([]string, 0, len(existing))\n\tfor _, m := range existing {\n\t\tif _, found := removeSet[m]; found {\n\t\t\tcontinue\n\t\t}\n\t\tresult = append(result, m)\n\t}\n\treturn result\n}\n\nfunc applyManualConfig(configPath string, cfg *Config, result providerTUIResult) error {\n\tif result.url == \"\" {\n\t\treturn fmt.Errorf(\"URL is required for manual configuration\")\n\t}\n\tif result.model == \"\" {\n\t\treturn fmt.Errorf(\"model is required for manual configuration\")\n\t}\n\n\tcfg.Provider = \"\"\n\tcfg.Model = \"\"\n\tcfg.Llm.URL = result.url\n\tcfg.Llm.Model = result.model\n\tcfg.Llm.AuthToken = result.apiKey\n\tauthHeader, err := llm.NormalizeAuthHeader(result.authHeader)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"invalid auth_header: %w\", err)\n\t}\n\tcfg.Llm.AuthHeader = authHeader\n\t// Write the canonical protocol so resolver picks it up directly. Also\n\t// mirror use_anthropic so configs read correctly on older binaries that\n\t// predate llm.protocol: anthropic -> true, the OpenAI family (including\n\t// openai-responses, which has no exact boolean equivalent) -> false, so\n\t// older binaries pick the OpenAI auth header/endpoint instead of wrongly\n\t// defaulting to anthropic.","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/alibaba/open-code-review/blob/5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f/cmd/opencodereview/provider_cmd.go#L90-L126","documentation":"applyManualConfig requires a model name when saving a manually configured provider and refuses to persist a config without one. Manual mode writes cfg.Llm.Model directly with no provider defaults, so an empty model would leave the resolved endpoint without a usable model ID.","triggerScenarios":"Confirming the manual-configuration screen of `ocr config provider` with the model field left empty; calling applyManualConfig with a providerTUIResult whose model field is \"\" (URL already non-empty, so the URL check passed).","commonSituations":"Entering a URL but forgetting the model in the TUI; assuming the tool will infer the model from the URL; test fixtures setting only the url field.","solutions":["Reopen `ocr config provider` and enter the model name (e.g. gpt-4o, claude-sonnet-4) in the manual form.","Use the built-in provider selection instead of manual mode to get model defaults.","In code/tests, set result.model before calling applyManualConfig."],"exampleFix":"// before\nresult := providerTUIResult{url: \"https://api.openai.com/v1\"}\n// after\nresult := providerTUIResult{url: \"https://api.openai.com/v1\", model: \"gpt-4o\"}","handlingStrategy":"validation","validationCode":"if result.model == \"\" {\n    return errors.New(\"model is required for manual configuration\")\n}","typeGuard":null,"tryCatchPattern":"if err := applyManualConfig(path, cfg, result); err != nil {\n    if strings.Contains(err.Error(), \"model is required\") {\n        // re-prompt for the model\n    }\n}","preventionTips":["Confirm the model name against the provider's model list before saving.","Enter both URL and model together when using manual configuration.","Use the provider preset flow to get sensible model defaults."],"tags":["validation","config","cli","tui"],"backgroundTag":"missing-required-argument","analyzedSha":"5cf97d0d15cbd41b602513c4be3bfec3cee5bf7f","analyzedAt":"2026-09-02T02:08:09.116Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}