Hmbown/CodeWhale · error · anyhow::Error
model uses , but this client is bound to and no…
Error message
{provider} model {model} uses {candidate_protocol}, but this client is bound to {wire_format} and no configuration is available to rebuild it What it means
rebound_for_model_protocol resolves the requested model through the route resolver; when the resolved protocol differs from the wire format this client was built with, the client must be rebuilt from the original Config. This error is raised when a cross-protocol model switch is requested but the `config` argument is None, so no rebuild is possible. It exists to guarantee a client never silently sends requests in the wrong wire dialect (e.g. Anthropic Messages payload to a Chat Completions endpoint).
Solutions
- Pass the original Config reference when calling rebound_for_model_protocol instead of None
- Retain the Config for the client's lifetime if mid-session model switching is expected
- Pick a model that resolves to the same protocol as the current binding, or construct a fresh client for the other protocol
- If a fallback chain triggers this, ensure fallback models resolve to compatible protocols or rebuild the client at fallback time with the config available
Example fix
// before let rebound = client.rebound_for_model_protocol(None, "claude-sonnet-4")?; // after let rebound = client.rebound_for_model_protocol(Some(&config), "claude-sonnet-4")?;
Defensive patterns
Strategy: fallback
Validate before calling
// Before switching models mid-session, confirm the target protocol is reachable:
let candidate = client.resolve_model_route(model)?;
let cross_protocol = candidate.protocol() != client.wire_format;
if cross_protocol && config.is_none() {
eprintln!("model {model} needs a protocol rebind; keep Config alive or pick a same-protocol model");
}
Try / catch
match client.rebound_for_model_protocol(config.as_ref(), &model) {
Ok(Some(rebound)) => { /* use rebound */ }
Ok(None) => { /* current binding already exact */ }
Err(e) if e.to_string().contains("no configuration is available") => {
// retain/restore Config and retry, or reject the model switch with a clear user message
}
Err(e) => return Err(e),
}
Prevention
- Keep the original Config alive for the client's lifetime when model switching is a feature
- Route same-protocol model changes only, or pre-build one client per protocol at startup
- In embedded/test runtimes, always pass Some(config) to rebound_for_model_protocol
- Check candidate.protocol() against the client binding before offering a model switch in the UI
When it happens
Trigger: Calling rebound_for_model_protocol(config=None, model=...) where the resolved route for `model` uses a different protocol than self.wire_format (e.g. an AnthropicMessages-bound client asked for a ChatCompletions model). The same-protocol path (client.rs:1805) succeeds without config; only cross-protocol switches hit this error.
Common situations: Embedded or test runtimes that construct a model-aware client and drop the original Config before switching models; switching to a fallback model that lives on a provider with a different wire protocol; a route/mid-session model change in a runtime that never retained Config.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- account_agent_model_unconfigured
- Auto has no concrete route yet; send a turn before warming…
- Codewhale stream-json contained an unknown event type
- computer_route_changed
- duplicate LSP Content-Length
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/72339b894f765109.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/client.rs:1817
if candidate.protocol() == self.wire_format
&& candidate.wire_model_id().as_str() == self.default_model
&& candidate_limits == self.route_limits
{
return Ok(None);
}
if candidate.protocol() == self.wire_format {
// Same-protocol model switches keep the already-authenticated,
// endpoint-bound transport but must freeze the alternate model's
// exact wire identity and limits. This path is also what makes a
// model-aware client usable in embedded/test runtimes that do not
// retain the original Config after construction.
let mut rebound = self.clone();
rebound.default_model = candidate.wire_model_id().as_str().to_string();
rebound.route_limits = candidate_limits;
return Ok(Some(rebound));
}
let config = config.ok_or_else(|| {
anyhow::anyhow!(
"{} model {:?} uses {:?}, but this client is bound to {:?} and no configuration is available to rebuild it",
self.api_provider.display_name(),
model,
candidate.protocol(),
self.wire_format
)
})?;
let mut rebound = Self::from_candidate(config, &candidate)?;
rebound.configured_models = Arc::clone(&self.configured_models);
Ok(Some(rebound))
}
fn bind_request_to_protocol(
&self,
mut request: MessageRequest,
) -> Result<(MessageRequest, Option<RouteLimits>)> {
let model_aware = self.api_provider.metadata().is_some_and(|provider| {
provider.wire_policy() == codewhale_config::provider::WirePolicy::ModelAwareView on GitHub (pinned to 73e0f67d83)