tonhowtf/omniget · error · std::io::Error

not found

Error message

{} not found

What it means

copy_recursive in the browser_extension export command requires the source path to exist before copying. When src does not exist it returns an io::Error with ErrorKind::NotFound and the message "<path> not found". This is a guard so browser_extension_export fails with a clear per-path message instead of copying nothing silently.

Solutions

  1. Check the source path exists before invoking the export and return a user-facing message listing valid browsers.
  2. Verify the browser name/profile mapping produces the correct directory for the installed browser version.
  3. Launch the source browser at least once so the profile and extension directory are created.
  4. Make copy_recursive skip missing source with a warning instead of failing the whole export when multiple sources are involved.

Example fix

// before
fn copy_recursive(src: &Path, dst: &Path) -> std::io::Result<()> {
    if !src.exists() {
        return Err(std::io::Error::new(std::io::ErrorKind::NotFound, format!("{} not found", src.display())));
    }
    ...
}

// after
fn copy_recursive(src: &Path, dst: &Path) -> std::io::Result<()> {
    if !src.exists() {
        tracing::warn!("source missing, skipping: {}", src.display());
        return Ok(()); // or map to a typed ExportError::SourceMissing(src.to_path_buf())
    }
    ...
}
Defensive patterns

Strategy: validation

Validate before calling

if (!src.existsSync(srcPath)) throw new Error(`extension source missing: ${srcPath}; is this browser installed?`);
await invoke('browser_extension_export', { browser });

Try / catch

try {
  await invoke('browser_extension_export', { browser });
} catch (msg) {
  if (typeof msg === 'string' && msg.endsWith('not found')) {
    showSetupHint(`No extension directory for "${browser}" — launch it once first.`);
  }
}

Prevention

When it happens

Trigger: browser_extension_export calls copy_recursive with a source directory (browser profile's extension folder, e.g. the browser_extension_dir for a given browser) that is missing on disk; or recursion encounters a child entry deleted between readdir and copy.

Common situations: User selects a browser they never launched (no profile/extension dir exists); unsupported or renamed browser profile layout; extension removed by the browser; wrong browser name key passed to the export command.

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 tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/c22dad8f27b2625e. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/src/commands/browser_extension.rs:36

fn read_bundled_manifest_version(app: &AppHandle, browser: &str) -> Option<String> {
    let resource = format!("browser-extension/{}/manifest.json", browser);
    let path = app
        .path()
        .resolve(resource, tauri::path::BaseDirectory::Resource)
        .ok()?;
    let raw = std::fs::read_to_string(&path).ok()?;
    let v: serde_json::Value = serde_json::from_str(&raw).ok()?;
    v.get("version")?.as_str().map(|s| s.to_string())
}

fn extension_export_dir(app: &AppHandle, browser: &str) -> Option<PathBuf> {
    let base = app.path().app_data_dir().ok()?;
    Some(base.join("browser-extension").join(browser))
}

fn copy_recursive(src: &Path, dst: &Path) -> std::io::Result<()> {
    if !src.exists() {
        return Err(std::io::Error::new(
            std::io::ErrorKind::NotFound,
            format!("{} not found", src.display()),
        ));
    }
    if src.is_file() {
        if let Some(parent) = dst.parent() {
            std::fs::create_dir_all(parent)?;
        }
        std::fs::copy(src, dst)?;
        return Ok(());
    }
    std::fs::create_dir_all(dst)?;
    for entry in std::fs::read_dir(src)? {
        let entry = entry?;
        let from = entry.path();
        let to = dst.join(entry.file_name());
        copy_recursive(&from, &to)?;
    }

View on GitHub (pinned to 8600b91f42)