{"record":{"id":"cf50658edf3b4ea5","repo":"tinyhumansai/openhuman","slug":"chat-factory-provider-string-p-has-an-empty","errorCode":null,"errorMessage":"[chat-factory] provider string '{p}' has an empty model — use '{form}'","messagePattern":"\\[chat-factory\\] provider string '(.+?)' has an empty model — use '(.+?)'","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/openhuman/inference/provider/factory.rs","lineNumber":1730,"sourceCode":"        return Some(Err(e));\n    }\n    if require_session {\n        #[cfg(not(test))]\n        if let Err(e) = verify_session_active(config) {\n            return Some(Err(e));\n        }\n    }\n\n    // Egress spine (privacy epic S2, #4436): committed to a local runtime here\n    // (past the non-local `None` return + access gates). Disclose it as\n    // NON-external — local inference never leaves the device, so\n    // `emit_external_transfer` records it without firing a pending event. This\n    // is the single local chokepoint for every ChatModel/turn entry.\n    emit_inference_egress(role, &p);\n\n    let unsupported = config.temperature_unsupported_models.clone();\n    let empty_model_err = |p: &str, form: &str| {\n        anyhow::anyhow!(\"[chat-factory] provider string '{p}' has an empty model — use '{form}'\")\n    };\n\n    // Resolve the local `api_key` + auth style shared by lmstudio/omlx/local-openai\n    // (Bearer when a key is configured, else no auth — same as the host builders).\n    let keyed_auth = || {\n        let api_key = config.local_ai.api_key.as_deref().unwrap_or(\"\").to_string();\n        let auth = if api_key.trim().is_empty() {\n            CompatAuthStyle::None\n        } else {\n            CompatAuthStyle::Bearer\n        };\n        (api_key, auth)\n    };\n    // First env override, else `local_ai.base_url`, else the profile default.\n    let env_or_config_url = |env: &str, default: &str| {\n        std::env::var(\"OPENHUMAN_LOCAL_INFERENCE_URL\")\n            .ok()\n            .filter(|s| !s.trim().is_empty())","sourceCodeStart":1712,"sourceCodeEnd":1748,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/inference/provider/factory.rs#L1712-L1748","documentation":"Generic factory guard: a recognized provider prefix was matched, but the model segment of the provider string is empty, so the formatted 'form' hint in the message tells the user the expected '<prefix>:<model>' shape. Thrown during chat-model construction after access gates pass.","triggerScenarios":"Thrown at src/openhuman/inference/provider/factory.rs:1730 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Rewrite the provider string in the shape shown in the error message, supplying a concrete model id after the prefix","Verify the role's provider field was not truncated or hand-edited in config.toml"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}