{"record":{"id":"dfe4cd2e2b1da5e6","repo":"jdx/mise","slug":"not-a-directory-src-dir-display","errorCode":null,"errorMessage":"not a directory: {src_dir.display}","messagePattern":"not a directory: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/oci/layer.rs","lineNumber":133,"sourceCode":"        return Err(format!(\"{name} must not be empty\"));\n    }\n    value\n        .parse::<u32>()\n        .map_err(|_| format!(\"{name} must be a non-negative integer <= {}\", u32::MAX))\n}\n\n/// Build a reproducible gzipped tar layer from files in `src_dir`, placing them\n/// under `target_prefix` inside the tar (e.g. `/mise/installs/node/20.0.0`).\n///\n/// `src_dir` must exist and be a directory. Symlinks are preserved; their\n/// targets are NOT followed. `owner` is applied to every emitted tar entry.\npub(crate) fn build_layer_from_dir(\n    src_dir: &Path,\n    target_prefix: &str,\n    owner: LayerOwner,\n) -> Result<LayerBlob> {\n    if !src_dir.is_dir() {\n        eyre::bail!(\"not a directory: {}\", src_dir.display());\n    }\n\n    let entries = collect_sorted_entries(src_dir, false, owner, None)?;\n    build_layer_from_entries(&entries, target_prefix, owner, None)\n}\n\n/// Build a tool layer while rebasing host paths embedded by its installer.\npub(crate) fn build_relocated_tool_layer_from_dir(\n    src_dir: &Path,\n    target_prefix: &str,\n    owner: LayerOwner,\n    relocation: &ToolRelocation,\n) -> Result<LayerBlob> {\n    if !src_dir.is_dir() {\n        eyre::bail!(\"not a directory: {}\", src_dir.display());\n    }\n\n    let entries = collect_sorted_entries(src_dir, false, owner, Some(relocation))?;","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/oci/layer.rs#L115-L151","documentation":"build_layer_from_dir builds an OCI layer from a host directory, and first verifies that src_dir actually is a directory. This error is thrown when the given path does not exist or is a file/symlink to something that is not a directory.","triggerScenarios":"Calling build_layer_from_dir (directly or via build_layer_from_path) with a path that is missing, a regular file, or a dangling symlink — `src_dir.is_dir()` returns false and the bail fires before collecting entries.","commonSituations":"Config pointing a copy/dir layer at a file instead of a directory; a path deleted or renamed since the config was written; relative path resolved from the wrong working directory; case-sensitivity mismatch on case-sensitive filesystems.","solutions":["Verify the path exists and is a directory: `ls -la <path>`; fix the path in the config or create the directory.","If you intended to copy a single file, use the file-copy path (build_layer_from_path) rather than the directory variant.","Check the working directory / relative path base the config is resolved against and use an absolute path if needed."],"exampleFix":"// before\nbuild_layer_from_dir(Path::new(\"assets/logo.png\"), \"app\", owner)\n// after\nbuild_layer_from_dir(Path::new(\"assets\"), \"app\", owner)","handlingStrategy":"validation","validationCode":"fn assert_dir(p: &Path) -> Result<()> {\n    if !p.is_dir() {\n        return Err(eyre!(\"not a directory: {}\", p.display()));\n    }\n    Ok(())\n}\nassert_dir(&src_dir)?;","typeGuard":"fn is_dir_or_fail(p: &Path) -> Option<&Path> {\n    if p.is_dir() { Some(p) } else { None }\n}","tryCatchPattern":"match build_layer_from_dir(&src, prefix, owner) {\n    Err(e) if e.to_string().starts_with(\"not a directory\") => {\n        eprintln!(\"{} missing or not a dir — fix the path or use the file-copy path\", src.display());\n    }\n    r => r,\n}","preventionTips":["Check the path exists and is a directory before configuring a dir layer.","Use absolute paths to avoid cwd-dependent resolution.","Re-check paths after refactors/renames of the source tree."],"tags":["oci","layer","filesystem"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}