zeroclaw-labs/zeroclaw · error
ModelPinnedProviderBuilder: pinned_model() is required
Error message
ModelPinnedProviderBuilder: pinned_model() is required
What it means
ModelPinnedProviderBuilder builds a provider that always routes to one fixed model under an alias. The pinned model has no sensible default, so build() panics if .pinned_model() was never called. The doc comment on the builder states that neither required field has a default.
Source
Thrown at crates/zeroclaw-providers/src/model_pin.rs:51
self.pinned_model = Some(model.to_string());
self
}
/// The inner provider whose model this pin overrides. Required.
pub fn inner(mut self, inner: Box<dyn ModelProvider>) -> Self {
self.inner = Some(inner);
self
}
/// # Panics
/// Panics if [`Self::pinned_model`] or [`Self::inner`] was not
/// called — neither has a sensible default.
pub fn build(self) -> ModelPinnedProvider {
ModelPinnedProvider {
alias: self.alias,
pinned_model: self
.pinned_model
.expect("ModelPinnedProviderBuilder: pinned_model() is required"),
inner: self
.inner
.expect("ModelPinnedProviderBuilder: inner() is required"),
}
}
}
impl ModelPinnedProvider {
/// Entry point. Only `alias` is taken positionally; the required
/// `pinned_model` and `inner` provider both go through labelled
/// chain methods so call sites cannot silently swap them.
pub fn builder(alias: &str) -> ModelPinnedProviderBuilder {
ModelPinnedProviderBuilder {
alias: alias.to_string(),
pinned_model: None,
inner: None,
}
}View on GitHub (pinned to 88bb9c8533)
Solutions
- Call .pinned_model("<provider-model-id>") on the builder before .build().
- If the model id comes from configuration, fail fast with a clear config error when it is missing instead of letting build() panic.
- Add a test that constructs every pinned provider declared in config.
Example fix
// before
let p = ModelPinnedProvider::builder()
.alias("fast")
.inner(inner)
.build(); // panics: pinned_model() is required
// after
let p = ModelPinnedProvider::builder()
.alias("fast")
.pinned_model("gpt-4o-mini")
.inner(inner)
.build(); Defensive patterns
Strategy: validation
Validate before calling
let pinned = config.pinned_model.clone()
.ok_or_else(|| anyhow::anyhow!("agent '{}' declares model pinning without a model id", alias))?;
let provider = ModelPinnedProvider::builder()
.alias(alias)
.pinned_model(pinned)
.inner(Box::new(inner))
.build(); Try / catch
let provider = std::panic::catch_unwind(|| builder.build())
.map_err(|_| anyhow::anyhow!("ModelPinnedProviderBuilder contract violated: pinned_model/inner required"))?; Prevention
- Provide pinned_model and inner together; they are both mandatory with no defaults.
- Validate model-pinning config entries at load time so a missing model id is a config error, not a runtime panic.
- Unit-test construction of every pinned provider declared in config.
When it happens
Trigger: Calling ModelPinnedProvider::builder().alias("name").inner(p).build() (or any construction path) without .pinned_model("model-id") beforehand.
Common situations: Setting up model pinning for an agent alias and wiring the delegate provider but forgetting the target model; changing the pinned model to come from config and the config lookup returning nothing so the setter is skipped.
Related errors
- ModelPinnedProviderBuilder: inner() is required
- OpenAiCompatibleBuilder: base_url() is required
- OpenAiCompatibleBuilder: auth_style() is required
- purge_agent not supported by this memory backend
- rename_agent not supported by this memory backend
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/c6fd010eadce1225.
Report an issue: GitHub.