gitbutlerapp/gitbutler · error · anyhow::Error
'{src}' is not a directory
Error message
'{src}' is not a directory What it means
`create_zip_file_from_dir()` in but-feedback requires `src_dir` to be an existing directory (it walks it with WalkDir to build the zip). A simple `is_dir()` check bails with the offending path when the source is missing or is a file. Note the message formats `src_dir.display()` while the guard itself is on `src_dir` — the path shown is the input directory path.
Source
Thrown at crates/but-feedback/src/zip.rs:21
io::{self, Read, Write},
path,
path::{Path, PathBuf},
};
use anyhow::{Result, bail};
use walkdir::{DirEntry, WalkDir};
use zip::{CompressionMethod, ZipWriter, write::SimpleFileOptions};
/// Create a zip file from the *contents* of `src_dir` and write the zip file out to `dst_file`,
/// possibly overwriting it if it exists.
pub fn create_zip_file_from_dir(
src_dir: impl AsRef<Path>,
dst_file: impl AsRef<Path>,
) -> anyhow::Result<PathBuf> {
let src_dir = src_dir.as_ref();
let dst_file = dst_file.as_ref();
if !src_dir.is_dir() {
bail!("'{src}' is not a directory", src = src_dir.display());
}
let file = fs::File::create(dst_file)?;
zip_dir(
&mut WalkDir::new(src_dir).into_iter().filter_map(Result::ok),
src_dir,
file,
)?;
Ok(dst_file.to_owned())
}
/// Create a zip file with `src` content in a single-file archive, with the file named `src_file_name`,
/// and write the zip file out to `dst_file`, possibly overwriting it if it exists.
pub fn create_zip_file_from_content(
src: &str,
src_file_name: &str,
dst_file: impl AsRef<Path>,View on GitHub (pinned to caf1f223d3)
Solutions
- Verify the path before calling: assert it exists and is a directory; print the canonical path on failure.
- Create the logs directory eagerly at application startup so it always exists by feedback time.
- Fix the configured path (trailing file component, wrong separator, env var empty).
- If the source may legitimately be absent, skip zip creation and report 'nothing to attach' instead.
Example fix
// before
let zip = but_feedback::zip::create_zip_file_from_dir(&maybe_wrong, &out)?;
// after
let dir = maybe_wrong.canonicalize().with_context(|| maybe_wrong.display().to_string())?;
anyhow::ensure!(dir.is_dir(), "{dir:?} is not a directory");
let zip = but_feedback::zip::create_zip_file_from_dir(&dir, &out)?; Defensive patterns
Strategy: validation
Validate before calling
// Rust — validate the source directory before zipping
let src = src_dir.as_ref();
if !src.is_dir() {
anyhow::bail!(
"log directory '{}' is missing; nothing to attach",
src.display()
);
}
let zip = but_feedback::zip::create_zip_file_from_dir(src, dst)?; Type guard
fn is_zip_source_dir(p: &std::path::Path) -> bool {
p.is_dir()
} Prevention
- Create the logs directory eagerly at app startup.
- Canonicalize configured paths at load time and fail fast on typos.
- Skip feedback attachment when the source is absent rather than propagating the error.
When it happens
Trigger: Calling feedback/log-zip creation with a path that doesn't exist, points to a regular file, or to a directory the process can't stat (permission-denied mount); race where the directory is deleted between composing the path and calling.
Common situations: Feedback bundle requested before logs directory was created; path built from a config value that's wrong (typo, wrong platform separator); containerized runs where the logs dir isn't mounted.
Related errors
- Cannot attempt to open anything but a directory: '{}'
- When using OpenAI in a bring your own key configuration, you
- BUG: we do not create or work with symlinks
- Path does not exist: {path}
- Path is not a directory: {path}
AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20).
Data as JSON: /api/errors/a1e42b98f4e36a3a.
Report an issue: GitHub.