getzola/zola · error

result cache lock

Error message

result cache lock

What it means

In LoadData::call the result_cache Mutex is locked with .expect("result cache lock"); a poisoned lock (another thread panicked while holding it) makes this panic. Normal concurrent locking with std::sync::Mutex never fails otherwise.

Source

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

                // source is None only with path_arg (not URL), so path_arg is safely unwrap
                return Err(Error::message(format!(
                    "`load_data`: {} doesn't exist",
                    self.base_path.join(path_arg.unwrap()).display()
                )));
            }
            (Ok(Some(data_source)), _) => data_source,
        };

        let file_format = get_output_format_from_args(format_arg, &data_source)?;
        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())

View on GitHub (pinned to 61d3082821)

Solutions

  1. Fix the underlying panic that poisoned the lock first (check earlier logs)
  2. Replace .expect with .unwrap_or_else(|p| p.into_inner()) to recover cached data despite poisoning
  3. Switch to parking_lot::Mutex which does not poison

Example fix

// before
let mut cache = self.result_cache.lock().expect("result cache lock");
// after
let mut cache = self
    .result_cache
    .lock()
    .unwrap_or_else(|poisoned| poisoned.into_inner());
Defensive patterns

Strategy: try-catch

Try / catch

let mut cache = match self.result_cache.lock() {
    Ok(c) => c,
    Err(poisoned) => {
        log::warn!("result cache poisoned, recovering data");
        poisoned.into_inner()
    }
};

Prevention

When it happens

Trigger: A previous thread panicked while holding the result_cache lock (e.g. during read_file or template evaluation inside call), poisoning the mutex; subsequent load_data template calls then panic.

Common situations: Parallel site builds where one worker thread panics on a bad file and all later load_data calls cascade-panic with 'PoisonError'.

Related errors


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