sigoden/aichat · error · anyhow::Error

Not found

Error message

Not found '{}'

What it means

list_files walks a path (recursively when called from expand_glob_paths) and bails with "Not found '<path>'" when the entry does not exist and bail_non_exist is true. It is a strict-existence check so glob expansion fails fast on missing roots.

Solutions

  1. Verify the path in the message exists relative to the working directory
  2. Fix the typo or update the config path after renaming/moving files
  3. Remove stale entries pointing at deleted files
  4. Use an absolute path or adjust the base directory if CWD differs

Example fix

// before
include = ["srcs/**/*.rs"]  // typo: no 'srcs' dir
// after
include = ["src/**/*.rs"]
Defensive patterns

Strategy: validation

Validate before calling

const fs = require('fs');
function assertPathsExist(paths) {
  for (const p of paths) {
    if (!fs.existsSync(p.split('*')[0].replace(/[^/]*$/, '') || '.')) {
      throw new Error(`base path missing for ${p}`);
    }
  }
}

Prevention

When it happens

Trigger: Expanding glob patterns whose base directory doesn't exist, or a config including a file path that was deleted/renamed, with the bail-on-missing option enabled.

Common situations: Typos in configured include paths; repository layout changed after config was written; running from a different working directory than the config assumes; case-sensitivity mismatches on Linux.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of sigoden/aichat@82976d349a (2026-09-09). Data as JSON: /api/errors/3488bddf0de68f27. Report an issue: GitHub.

Appendix: source

Thrown at src/utils/path.rs:164

        Ok((base_path, extensions, current_only))
    } else if path_str.ends_with("/**") || path_str.ends_with(r"\**") {
        Ok((path_str[0..path_str.len() - 3].to_string(), None, false))
    } else {
        Ok((path_str.to_string(), None, false))
    }
}

#[async_recursion::async_recursion]
async fn list_files(
    files: &mut IndexSet<String>,
    entry_path: &Path,
    suffixes: Option<&Vec<String>>,
    current_only: bool,
    bail_non_exist: bool,
) -> Result<()> {
    if !entry_path.exists() {
        if bail_non_exist {
            bail!("Not found '{}'", entry_path.display());
        } else {
            return Ok(());
        }
    }
    if entry_path.is_dir() {
        let mut reader = tokio::fs::read_dir(entry_path).await?;
        while let Some(entry) = reader.next_entry().await? {
            let path = entry.path();
            if path.is_dir() {
                if !current_only {
                    list_files(files, &path, suffixes, current_only, bail_non_exist).await?;
                }
            } else {
                add_file(files, suffixes, &path);
            }
        }
    } else {
        add_file(files, suffixes, entry_path);

View on GitHub (pinned to 82976d349a)