{"record":{"id":"6dca8b96cab68fbf","repo":"getzola/zola","slug":"result-cache-lock","errorCode":null,"errorMessage":"result cache lock","messagePattern":"result cache lock","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"components/templates/src/functions/files.rs","lineNumber":155,"sourceCode":"            }\n\n            let path_with_lang = segments.join(\"/\");\n\n            let mut permalink = self.config.make_permalink(&path_with_lang);\n            if !trailing_slash && permalink.ends_with('/') {\n                permalink.pop(); // Removes the slash\n            }\n\n            if cachebust {\n                match search_for_file(\n                    &self.base_path,\n                    &path_with_lang,\n                    &self.config.theme,\n                    &self.output_path,\n                )\n                .map_err(|e| Error::message(format!(\"`get_url`: {}\", e)))?\n                .and_then(|(file_path, unified_path)| {\n                    let mut cache = self.result_cache.lock().expect(\"result cache lock\");\n                    if let Some(hash) = cache.get(&unified_path) {\n                        return Some(hash.clone());\n                    }\n                    let mut f = fs::File::open(file_path).ok()?;\n                    let mut contents = Vec::new();\n                    f.read_to_end(&mut contents).ok()?;\n                    let hash = compute_hash::<Sha256>(&contents, false);\n                    cache.insert(unified_path, hash.clone());\n                    Some(hash)\n                }) {\n                    Some(hash) => {\n                        let short_hash = &hash[..20]; // 2^-80 chance of false positive\n                        permalink = format!(\"{permalink}?h={short_hash}\");\n                    }\n                    None => {\n                        return Err(Error::message(format!(\n                            \"`get_url`: Could not find or open file {}\",\n                            path_with_lang","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/getzola/zola/blob/61d30828217957120309db657950224edf9707e2/components/templates/src/functions/files.rs#L137-L173","documentation":"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'.","triggerScenarios":"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).","commonSituations":"Multithreaded template rendering (server/live-reload) where one request panics in get_url and later requests hit the poisoned mutex.","solutions":["Fix the original panic inside get_url's cache/hash code; it appears earlier in the log.","Replace expect with unwrap_or_else(|p| p.into_inner()) to survive poisoning (the cache is a plain HashMap).","Restart the rendering server after a panic instead of reusing the poisoned state.","Guard the cache body so hash computation returns Result instead of panicking."],"exampleFix":"// before\nlet mut cache = self.result_cache.lock().expect(\"result cache lock\");\n// after\nlet mut cache = self.result_cache.lock().unwrap_or_else(|p| p.into_inner());","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"let mut cache = match self.result_cache.lock() {\n    Ok(g) => g,\n    Err(poisoned) => poisoned.into_inner(), // cache is recoverable state\n};","preventionTips":["Fix panics inside get_url's file-reading path first — they poison the shared cache.","Restart the template server after a panic rather than continuing.","Return Result from cache computations instead of panicking under the lock.","Use into_inner() recovery for caches, whose state is always rebuildable."],"tags":["mutex","poisoned-lock","templates","concurrency"],"backgroundTag":"mutex-poisoned","analyzedSha":"61d30828217957120309db657950224edf9707e2","analyzedAt":"2026-09-03T14:39:09.727Z","contentChangedAt":"2026-09-03T14:39:09.727Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}