getzola/zola · error

response client lock

Error message

response client lock

What it means

When load_data fetches a URL, the shared reqwest client behind a Mutex is locked with .expect("response client lock"). If the mutex was poisoned by a panic in another thread while performing a request, this call panics with a PoisonError message.

Source

Thrown at components/templates/src/functions/load_data.rs:327

        let cache_key = data_source.get_cache_key(
            &file_format,
            method,
            &post_body_arg,
            &post_content_type,
            &headers,
        );

        let mut cache = self.result_cache.lock().expect("result cache lock");
        if let Some(cached_result) = cache.get(&cache_key) {
            return Ok(cached_result.clone());
        }

        let data = match data_source {
            DataSource::Path(path) => read_file(&path).map_err(|e| {
                Error::message(format!("`load_data`: error reading file {:?}: {}", path, e))
            }),
            DataSource::Url(url) => {
                let response_client = self.client.lock().expect("response client lock");
                let req = match method {
                    Method::Get => response_client
                        .get(url.as_str())
                        .headers(add_headers_from_args(headers)?)
                        .header(header::ACCEPT, file_format.as_accept_header()),
                    Method::Post => {
                        let mut resp = response_client
                            .post(url.as_str())
                            .headers(add_headers_from_args(headers)?)
                            .header(header::ACCEPT, file_format.as_accept_header());
                        if let Some(content_type) = post_content_type {
                            match HeaderValue::from_str(&content_type) {
                                Ok(c) => {
                                    resp = resp.header(CONTENT_TYPE, c);
                                }
                                Err(_) => {
                                    return Err(Error::message(format!(
                                        "`load_data`: {} is an illegal content type",

View on GitHub (pinned to 61d3082821)

Solutions

  1. Find and fix the original panic that poisoned the client mutex
  2. Use .unwrap_or_else(|p| p.into_inner()) to tolerate poisoning
  3. Store the reqwest Client without a Mutex (reqwest::Client is Arc internally and Sync) to eliminate the lock entirely

Example fix

// before
let response_client = self.client.lock().expect("response client lock");
// after
let response_client = self
    .client
    .lock()
    .unwrap_or_else(|poisoned| poisoned.into_inner());
Defensive patterns

Strategy: try-catch

Try / catch

let response_client = match self.client.lock() {
    Ok(c) => c,
    Err(poisoned) => poisoned.into_inner(),
};

Prevention

When it happens

Trigger: A previous load_data URL request panicked while holding self.client (e.g. inside the request-building closure); the next remote-data call locks the poisoned mutex.

Common situations: Parallel template rendering of many remote loads where one thread panics (network/DNS panic path) and remaining renders cascade.

Related errors


AI-assisted analysis of getzola/zola@61d3082821 (2026-09-03). Data as JSON: /api/errors/ac1739786592c9ed. Report an issue: GitHub.