getzola/zola · error
Couldn't lock imageproc (num_img_ops)
Error message
Couldn't lock imageproc (num_img_ops)
What it means
Site::num_img_ops locks the shared imageproc Mutex to report the number of pending image operations, panicking with this expect message if the lock cannot be acquired. As with other imageproc lock sites, this only happens when the mutex is poisoned by a panic in another thread holding it.
Source
Thrown at components/site/src/lib.rs:686
false,
None,
)?;
}
// We're fine with missing static folders
if self.static_path.exists() {
copy_directory(
&self.static_path,
&self.output_path,
self.config.hard_link_static,
self.config.ignored_static_globset.as_ref(),
)?;
}
Ok(())
}
pub fn num_img_ops(&self) -> usize {
let imageproc = self.imageproc.lock().expect("Couldn't lock imageproc (num_img_ops)");
imageproc.num_img_ops()
}
pub fn process_images(&self) -> Result<()> {
let mut imageproc =
self.imageproc.lock().expect("Couldn't lock imageproc (process_images)");
imageproc.prune()?;
imageproc.do_process()
}
/// Deletes the `public` directory if it exists and the `preserve_dotfiles_in_output` option is set to false,
/// or if set to true: its contents except for the dotfiles at the root level.
pub fn clean(&self) -> Result<()> {
clean_site_output_folder(&self.output_path, self.config.preserve_dotfiles_in_output)
}
fn copy_assets(&self, parent: &Path, assets: &[impl AsRef<Path>], dest: &Path) -> Result<()> {
for asset in assets {View on GitHub (pinned to 61d3082821)
Solutions
- Fix the root-cause panic that poisoned the mutex; check earlier log output for the original backtrace.
- Use unwrap_or_else(|p| p.into_inner()) to tolerate poisoning when reading the count.
- Avoid invoking num_img_ops once a build failure is known.
- Serialize access so image-processing panics are handled before the count is queried.
Example fix
// before
let imageproc = self.imageproc.lock().expect("Couldn't lock imageproc (num_img_ops)");
// after
let imageproc = self.imageproc.lock().unwrap_or_else(|p| p.into_inner()); Defensive patterns
Strategy: try-catch
Try / catch
let n = match site.imageproc.lock() {
Ok(g) => g.num_img_ops(),
Err(poisoned) => poisoned.into_inner().num_img_ops(),
}; Prevention
- Query counts only after a successful build phase.
- Handle build errors so worker panics don't poison shared state.
- Restart the build/server after any panic.
- Wrap image ops to return Result rather than panicking.
When it happens
Trigger: Calling num_img_ops after the imageproc mutex was poisoned by a panic elsewhere (e.g. during process_images or a template-driven image operation).
Common situations: Build tooling that reports image op counts after a partial/failed build in which an image worker panicked.
Related errors
- Couldn't lock imageproc (set_base_url)
- result cache lock
- Couldn't lock imageproc (process_images)
- result cache lock
- response client lock
AI-assisted analysis of getzola/zola@61d3082821 (2026-09-03).
Data as JSON: /api/errors/28e0fa6c43068eb9.
Report an issue: GitHub.