{"record":{"id":"b3fdb4f66aa0c6ea","repo":"getzola/zola","slug":"image-output-path-should-contain-a-parent-d","errorCode":null,"errorMessage":"Image output path '{:?}' should contain a parent directory, but doesn't","messagePattern":"Image output path '(.+?)' should contain a parent directory, but doesn't","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"components/imageproc/src/processor.rs","lineNumber":94,"sourceCode":"            log::debug!(\n                \"No exif orientation data for {}, using default orientation\",\n                self.input_path.display(),\n            );\n            img\n        };\n\n        let img = match self.instr.crop_instruction {\n            Some((x, y, w, h)) => img.crop(x, y, w, h),\n            None => img,\n        };\n        let img = match self.instr.resize_instruction {\n            Some((w, h)) => img.resize_exact(w, h, self.filter),\n            None => img,\n        };\n\n        let tmp_output_file = match self.output_path.parent() {\n            Some(parent) => Ok(NamedTempFile::new_in(parent)?),\n            None => Err(anyhow!(\n                \"Image output path '{:?}' should contain a parent directory, but doesn't\",\n                self.output_path\n            )),\n        }?;\n        let mut tmp_output_writer = BufWriter::new(&tmp_output_file);\n\n        let has_color_profile = color_profile.is_some();\n        let add_color_profile = |encoder: &mut dyn ImageEncoder| {\n            if let Some(color_profile) = color_profile {\n                let _ = encoder.set_icc_profile(color_profile).inspect_err(|_| log::warn!(\"processing {}: Image encoder for {} does not support color profiles, colors may be incorrect.\", self.input_path.display(), self.format.extension()));\n            }\n        };\n\n        match self.format {\n            Format::Png => {\n                let mut encoder = PngEncoder::new(&mut tmp_output_writer);\n                add_color_profile(&mut encoder);\n                img.write_with_encoder(encoder)?;","sourceCodeStart":76,"sourceCodeEnd":112,"githubUrl":"https://github.com/getzola/zola/blob/61d30828217957120309db657950224edf9707e2/components/imageproc/src/processor.rs#L76-L112","documentation":"`ImageProcessor::perform` writes the processed image to a NamedTempFile created in the output path's parent directory before moving it into place. If `output_path` has no parent (e.g. a bare filename like \"out.png\" resolved to an empty parent), the atomic temp-file strategy cannot work and this error is returned.","triggerScenarios":"Calling the image processor with an `output_path` whose `.parent()` is `None` or points to nothing usable — typically a root-relative bare filename without a directory component.","commonSituations":"Config value like `output = \"image.png\"` instead of `output = \"static/processed/image.png\"`; path constructed with Path::new(\"file.png\") lacking a directory; working-directory assumptions differing between dev and prod.","solutions":["Provide a full path including a parent directory for the output file","Ensure the parent directory exists and is writable","If input is user-controlled, canonicalize/normalize the path and reject bare filenames"],"exampleFix":"// before\noutput_path = \"processed.png\"\n// after\noutput_path = \"static/processed/processed.png\"","handlingStrategy":"validation","validationCode":"use std::path::{Path, PathBuf};\nfn ensure_parent(output: &Path) -> std::io::Result<PathBuf> {\n    let parent = output.parent().filter(|p| !p.as_os_str().is_empty())\n        .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::InvalidInput, \"output path has no parent directory\"))?.to_path_buf();\n    std::fs::create_dir_all(&parent)?;\n    Ok(parent)\n}","typeGuard":"fn has_parent_dir(p: &Path) -> bool {\n    p.parent().map_or(false, |p| !p.as_os_str().is_empty())\n}","tryCatchPattern":"match processor.perform() {\n    Ok(_) => {},\n    Err(e) if e.to_string().contains(\"should contain a parent directory\") => {\n        log::error!(\"output_path {:?} is a bare filename; add a directory component\", output_path);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Always configure output paths with an explicit directory (e.g. static/processed/out.png), never a bare filename","Canonicalize the configured path at startup and assert it has a parent","Create parent directories (create_dir_all) as part of setup before processing"],"tags":["filesystem","paths","image-processing"],"backgroundTag":"invalid-output-path","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"}