getzola/zola · error

result cache lock

Error message

result cache lock

What it means

The get_url template function caches file hashes in a shared result_cache Mutex. This expect panics when the cache mutex is poisoned — another thread panicked while holding the lock — so subsequent get_url calls in any template render abort with 'result cache lock'.

Source

Thrown at components/templates/src/functions/files.rs:155

            }

            let path_with_lang = segments.join("/");

            let mut permalink = self.config.make_permalink(&path_with_lang);
            if !trailing_slash && permalink.ends_with('/') {
                permalink.pop(); // Removes the slash
            }

            if cachebust {
                match search_for_file(
                    &self.base_path,
                    &path_with_lang,
                    &self.config.theme,
                    &self.output_path,
                )
                .map_err(|e| Error::message(format!("`get_url`: {}", e)))?
                .and_then(|(file_path, unified_path)| {
                    let mut cache = self.result_cache.lock().expect("result cache lock");
                    if let Some(hash) = cache.get(&unified_path) {
                        return Some(hash.clone());
                    }
                    let mut f = fs::File::open(file_path).ok()?;
                    let mut contents = Vec::new();
                    f.read_to_end(&mut contents).ok()?;
                    let hash = compute_hash::<Sha256>(&contents, false);
                    cache.insert(unified_path, hash.clone());
                    Some(hash)
                }) {
                    Some(hash) => {
                        let short_hash = &hash[..20]; // 2^-80 chance of false positive
                        permalink = format!("{permalink}?h={short_hash}");
                    }
                    None => {
                        return Err(Error::message(format!(
                            "`get_url`: Could not find or open file {}",
                            path_with_lang

View on GitHub (pinned to 61d3082821)

Solutions

  1. Fix the original panic inside get_url's cache/hash code; it appears earlier in the log.
  2. Replace expect with unwrap_or_else(|p| p.into_inner()) to survive poisoning (the cache is a plain HashMap).
  3. Restart the rendering server after a panic instead of reusing the poisoned state.
  4. Guard the cache body so hash computation returns Result instead of panicking.

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(|p| p.into_inner());
Defensive patterns

Strategy: try-catch

Try / catch

let mut cache = match self.result_cache.lock() {
    Ok(g) => g,
    Err(poisoned) => poisoned.into_inner(), // cache is recoverable state
};

Prevention

When it happens

Trigger: Rendering a template that calls get_url after a panic occurred while another thread held result_cache (e.g. an earlier get_url panicked computing a hash).

Common situations: Multithreaded template rendering (server/live-reload) where one request panics in get_url and later requests hit the poisoned mutex.

Related errors


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