{"record":{"id":"1ac22e6f5a75f7ff","repo":"getzola/zola","slug":"couldn-t-lock-imageproc-set-base-url","errorCode":null,"errorMessage":"Couldn't lock imageproc (set_base_url)","messagePattern":"Couldn't lock imageproc \\(set_base_url\\)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"components/site/src/lib.rs","lineNumber":174,"sourceCode":"        self.live_reload = get_available_port(interface, port_to_avoid);\n    }\n\n    /// Only used in `zola serve` to re-use the initial websocket port\n    pub fn enable_live_reload_with_port(&mut self, live_reload_port: u16) {\n        self.live_reload = Some(live_reload_port);\n    }\n\n    /// Reloads the templates and rebuild the site without re-markdown the Markdown.\n    pub fn reload_templates(&mut self) -> Result<()> {\n        self.tera = load_tera(&self.base_path, &self.config)?;\n        tpls::register_early_global_fns(self);\n        // TODO: be smarter than that, no need to recompile sass for example\n        self.build()\n    }\n\n    pub fn set_base_url(&mut self, base_url: String) {\n        self.config.base_url = base_url;\n        let mut imageproc = self.imageproc.lock().expect(\"Couldn't lock imageproc (set_base_url)\");\n        imageproc.set_base_url(&self.config);\n    }\n\n    pub fn set_output_path<P: AsRef<Path>>(&mut self, path: P) {\n        self.output_path = path.as_ref().to_path_buf();\n    }\n\n    pub fn minify(&mut self) {\n        self.config.minify_html = true;\n    }\n\n    /// Reads all .md files in the `content` directory and create pages/sections\n    /// out of them\n    pub fn load(&mut self) -> Result<()> {\n        self.library = Arc::new(Library::new(&self.config));\n\n        // not the most elegant loop, but this is necessary to use skip_current_dir\n        // which we can only decide to use after we've deserialised the section","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/getzola/zola/blob/61d30828217957120309db657950224edf9707e2/components/site/src/lib.rs#L156-L192","documentation":"Site::set_base_url locks the Site's imageproc Mutex (a std::sync::Mutex guard shared with other threads, e.g. the template functions) and panics with this expect message if the lock is unavailable. A std Mutex only fails when the mutex is poisoned — i.e. another thread panicked while holding it — or on unrecoverable locking errors.","triggerScenarios":"Calling set_base_url after any thread holding the imageproc lock has panicked (poisoned mutex). With ReentrantLock-like re-entrancy in older code, also calling it from a thread that already holds the lock.","commonSituations":"A panic inside image processing (e.g. in get_image_metadata or resize_image template functions) poisons the mutex; a later set_base_url call then panics with this message.","solutions":["Fix the original panic that poisoned the imageproc mutex (look for an earlier panic backtrace in the logs).","Use lock().unwrap_or_else(|p| p.into_inner()) to recover from poisoning if the data is still consistent.","Ensure no code path calls set_base_url after a worker thread has failed.","If re-entrancy is possible (set_base_url called from within image processing), restructure to avoid nested locking."],"exampleFix":"// before\nlet mut imageproc = self.imageproc.lock().expect(\"Couldn't lock imageproc (set_base_url)\");\n// after\nlet mut imageproc = self.imageproc.lock().unwrap_or_else(|p| p.into_inner());","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Recover from a poisoned mutex instead of panicking\nlet mut imageproc = match site.imageproc.lock() {\n    Ok(g) => g,\n    Err(poisoned) => poisoned.into_inner(), // log and recover\n};","preventionTips":["Fix any earlier image-processing panic before calling set_base_url again.","Restart the process after a panic rather than reusing the poisoned Site.","Avoid nested/re-entrant calls that hold the imageproc lock.","Prefer unwrap_or_else(|p| p.into_inner()) at lock sites where state stays valid."],"tags":["mutex","poisoned-lock","concurrency","panic"],"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"}