Kuberwastaken/claurst · critical
AnthropicProvider::from_config: failed to create…
Error message
AnthropicProvider::from_config: failed to create AnthropicClient
What it means
AnthropicProvider::from_config builds an AnthropicClient from the given ClientConfig and calls .expect() on the result, panicking if client construction fails. The panic message surfaces this string. Construction fails when the config cannot produce a valid HTTP client (e.g. TLS backend init failure).
Solutions
- Prefer the fallible constructor (AnthropicClient::new / provider constructors that return Result) and propagate the error instead of relying on from_config.
- Check that exactly one TLS backend is available (feature flags: rustls vs native-tls) in your build.
- If cross-compiling, ensure the TLS library links correctly for the target.
- Enable the `tls` feature of reqwest if all TLS features were disabled.
- If this panic fires in practice, capture the underlying reqwest build error by constructing AnthropicClient::new(config) manually and inspecting the Result.
Example fix
// before
let provider = AnthropicProvider::from_config(config); // panics on failure
// after
let client = AnthropicClient::new(config).context("creating Anthropic client")?;
let provider = AnthropicProvider { client: Arc::new(client), id: ProviderId::new(ProviderId::ANTHROPIC) }; Defensive patterns
Strategy: validation
Validate before calling
// ensure reqwest has a TLS backend at build time
cargo tree -i reqwest # verify default-tls or rustls-tls is enabled
// and construct the client early with a proper error instead of from_config
let client = AnthropicClient::new(config).map_err(|e| anyhow!("Anthropic client init failed: {e}"))?; Try / catch
// avoid the panicking path; use the fallible construction and catch it
match AnthropicClient::new(config) {
Ok(client) => Ok(AnthropicProvider { client: Arc::new(client), id: ProviderId::new(ProviderId::ANTHROPIC) }),
Err(e) => Err(anyhow!("failed to create Anthropic client: {e}")),
} Prevention
- Do not call from_config in library code paths where a panic is unacceptable; construct AnthropicClient directly.
- Verify TLS feature flags at build time (rustls-tls or native-tls exactly once).
- Smoke-test client construction at startup, before user interaction.
- Avoid conflicting reqwest features across workspace dependencies.
When it happens
Trigger: Calling AnthropicProvider::from_config with a ClientConfig whose reqwest client builder fails to build — practically only TLS backend initialization failure, since config shape is fixed.
Common situations: Static-linking or cross-compiling without a TLS backend (rustls/native-tls mismatch); running in an environment where OpenSSL cannot be initialized. Note the crate convention elsewhere is to propagate; this expect is an internal invariant.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- failed to build reqwest client
- failed to build reqwest client
- failed to build reqwest client
- failed to build reqwest client
- failed to build reqwest client
AI-assisted analysis of Kuberwastaken/claurst@b0637c97ec (2026-09-10).
Data as JSON: /api/errors/4931acfbe9f2896b.
Report an issue: GitHub.
Appendix: source
Thrown at src-rust/crates/api/src/providers/anthropic.rs:52
/// `Arc<dyn LlmProvider>`.
pub struct AnthropicProvider {
client: Arc<AnthropicClient>,
id: ProviderId,
}
impl AnthropicProvider {
/// Wrap an already-constructed (and Arc-wrapped) [`AnthropicClient`].
pub fn new(client: Arc<AnthropicClient>) -> Self {
Self {
client,
id: ProviderId::new(ProviderId::ANTHROPIC),
}
}
/// Construct directly from a [`ClientConfig`], creating the inner client.
pub fn from_config(config: ClientConfig) -> Self {
let client = AnthropicClient::new(config)
.expect("AnthropicProvider::from_config: failed to create AnthropicClient");
Self {
client: Arc::new(client),
id: ProviderId::new(ProviderId::ANTHROPIC),
}
}
/// Build a [`CreateMessageRequest`] from a [`ProviderRequest`].
fn build_request(request: &ProviderRequest) -> CreateMessageRequest {
let normalized_messages = normalize_anthropic_messages(&request.messages);
let api_messages: Vec<ApiMessage> = normalized_messages
.iter()
.map(ApiMessage::from)
.collect();
let api_tools: Option<Vec<ApiToolDefinition>> = if request.tools.is_empty() {
None
} else {
Some(request.tools.iter().map(ApiToolDefinition::from).collect())
View on GitHub (pinned to b0637c97ec)