{"record":{"id":"924e9a351fb8295a","repo":"zeroclaw-labs/zeroclaw","slug":"model-provider-reference-must-not-be-empty","errorCode":null,"errorMessage":"model_provider reference must not be empty","messagePattern":"model_provider reference must not be empty","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/orchestrator/mod.rs","lineNumber":1622,"sourceCode":"        .get(agent_alias)\n        .with_context(|| format!(\"agents.{agent_alias} is not configured\"))?;\n    let configured = agent.model_provider.trim();\n    if configured.is_empty() {\n        anyhow::bail!(\n            \"agents.{agent_alias}.model_provider is empty; runtime reload requires a dotted `<type>.<alias>` provider reference\"\n        );\n    }\n    let (model_provider, _) = model_provider_entry_for_ref(config, configured)?;\n    Ok(model_provider)\n}\n\nfn model_provider_entry_for_ref<'a>(\n    config: &'a Config,\n    model_provider: &str,\n) -> anyhow::Result<(String, &'a zeroclaw_config::schema::ModelProviderConfig)> {\n    let trimmed = model_provider.trim();\n    if trimmed.is_empty() {\n        anyhow::bail!(\"model_provider reference must not be empty\");\n    }\n\n    let Some((provider_type, provider_alias)) = trimmed.split_once('.') else {\n        anyhow::bail!(\"model_provider `{trimmed}` must use `<type>.<alias>` form\");\n    };\n    let Some(entry) = config.providers.models.find(provider_type, provider_alias) else {\n        anyhow::bail!(\"model_provider `{trimmed}` does not resolve to a configured provider\");\n    };\n    Ok((trimmed.to_string(), entry))\n}\n\n/// Resolve runtime defaults from `config` against a specific dotted\n/// `model_provider` reference (`\"<type>.<alias>\"`) — the per-agent\n/// resolution path.\nfn runtime_defaults_from_config(\n    config: &Config,\n    model_provider: &str,\n) -> anyhow::Result<ChannelRuntimeDefaults> {","sourceCodeStart":1604,"sourceCodeEnd":1640,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/orchestrator/mod.rs#L1604-L1640","documentation":"Thrown by model_provider_entry_for_ref when the model_provider string is empty (or only whitespace) after trimming. This is the low-level guard behind dotted-ref resolution: before any `<type>.<alias>` split is attempted, the reference must be non-empty. Callers reach it from resolved_runtime_model_provider_ref and any other code resolving a raw provider reference against `config.providers.models`.","triggerScenarios":"Calling model_provider_entry_for_ref(config, \"\") or with a whitespace-only string; typically the downstream result of an agents entry, CLI argument, or gateway payload that carried an empty provider reference.","commonSituations":"Upstream code reads an optional field with `.unwrap_or_default()` and passes the empty string along; gateway/JSON payload where model_provider was omitted but the field type forced \"\"; whitespace-only value pasted into config.","solutions":["Find the caller that produced the empty reference and fix the source value (agent config field, CLI arg, or API payload)","If the reference is optional in your flow, check emptiness before calling the resolver instead of relying on the error","Set a valid dotted ref such as `openai.default` at the origin"],"exampleFix":"// before\nlet (r, entry) = model_provider_entry_for_ref(&config, agent.model_provider.as_str())?;\n\n// after\nlet provider_ref = agent.model_provider.trim();\nif provider_ref.is_empty() {\n    anyhow::bail!(\"agent `{alias}` has no model_provider configured\");\n}\nlet (r, entry) = model_provider_entry_for_ref(&config, provider_ref)?;","handlingStrategy":"validation","validationCode":"let provider_ref = model_provider.trim();\nif provider_ref.is_empty() {\n    anyhow::bail!(\"model_provider reference is empty at source `{source}`\");\n}\nlet (ref_, entry) = model_provider_entry_for_ref(config, provider_ref)?;","typeGuard":null,"tryCatchPattern":"Err(err) if err.to_string() == \"model_provider reference must not be empty\" => {\n    // reject the payload/request that carried the empty reference\n}","preventionTips":["Never unwrap Option<String> provider fields with default(\"\"), propagate the Option and validate","Reject empty model_provider at the API/gateway boundary before it reaches the resolver","Trim and assert non-empty in one helper so all call sites share the guard"],"tags":["model-provider","empty-value","validation","zeroclaw"],"backgroundTag":"empty-required-field","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}