{"record":{"id":"32c177ff42450f60","repo":"BigPizzaV3/CodexPlusPlus","slug":"error-32c177","errorCode":null,"errorMessage":"供应商名称为空","messagePattern":"供应商名称为空","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/provider_import.rs","lineNumber":223,"sourceCode":"        model_vlm: String::new(),\n        vlm_api_key: String::new(),\n        vlm_model: String::new(),\n        vlm_base_url: String::new(),\n        user_agent: String::new(),\n        sub2api_enabled: false,\n        sub2api_multiplier: String::new(),\n        model_routes: Vec::new(),\n    }\n}\n\nfn normalize_request(mut request: ProviderImportRequest) -> anyhow::Result<ProviderImportRequest> {\n    request.name = request.name.trim().to_string();\n    request.base_url = request.base_url.trim().trim_end_matches('/').to_string();\n    request.api_key = request.api_key.trim().to_string();\n    request.wire_api = request.wire_api.trim().to_ascii_lowercase();\n    request.relay_mode = request.relay_mode.trim().to_ascii_lowercase();\n    if request.name.is_empty() {\n        anyhow::bail!(\"供应商名称为空\");\n    }\n    if request.base_url.is_empty() {\n        anyhow::bail!(\"Base URL 为空\");\n    }\n    if request.api_key.is_empty() {\n        anyhow::bail!(\"API Key 为空\");\n    }\n    request.config_contents = build_config_toml(\n        &request.base_url,\n        &request.api_key,\n        relay_protocol(&request.wire_api),\n    );\n    request.auth_contents = build_auth_json(&request.api_key);\n    Ok(request)\n}\n\nfn relay_protocol(value: &str) -> RelayProtocol {\n    match value.trim().to_ascii_lowercase().as_str() {","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/1f431ae49b57b3055e0e6845ba6156c6b4232b4d/crates/codex-plus-core/src/provider_import.rs#L205-L241","documentation":"Thrown by normalize_request in crates/codex-plus-core/src/provider_import.rs when a provider import request's name field is empty after trimming. Every imported provider becomes a RelayProfile whose name is required, so the import aborts before creating config/auth contents. Input reaches this function either from the manager UI or from request_from_url parsing the name query parameter of a share link.","triggerScenarios":"POSTing an import request with name omitted, blank, or only whitespace; importing from a share URL whose name= query parameter is empty (e.g. ?name=&baseUrl=...); URL-encoding issue dropping the name value.","commonSituations":"Share links generated with an unset name; frontend form submitted before the name field was filled; percent-encoding bugs where name resolves to empty.","solutions":["Provide a non-empty provider name (any non-whitespace text) in the import request","For URL imports, check the share link contains name=YourProvider (URL-encoded if it has spaces)","Fix the frontend to require the name field before submitting the import"],"exampleFix":"# before\nhttps://app/import?name=&baseUrl=https%3A%2F%2Fapi.vendor.com&apiKey=sk-...\n\n# after\nhttps://app/import?name=VendorAI&baseUrl=https%3A%2F%2Fapi.vendor.com&apiKey=sk-...","handlingStrategy":"validation","validationCode":"fn import_request_valid(req: &ProviderImportRequest) -> bool {\n    !req.name.trim().is_empty()\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Make the name field required in the import UI before submit","When generating share links, omit the link or warn if name is empty","URL-encode name values containing spaces or non-ASCII characters"],"tags":["provider-import","validation","required-field","share-link"],"backgroundTag":"missing-required-field","analyzedSha":"1f431ae49b57b3055e0e6845ba6156c6b4232b4d","analyzedAt":"2026-08-16T20:54:18.598Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}