sigoden/dufs · error · anyhow::Error

Path ` ` doesn't contains index.html

Error message

Path `{}` doesn't contains index.html

What it means

sanitize_assets_path in src/args.rs first runs sanitize_path, then requires that the assets directory contains an index.html file. If <assets>/index.html is missing it bails with "Path `<path>` doesn't contains index.html". dufs serves the bundled UI from this directory, so an index.html is mandatory for custom asset overrides.

Solutions

  1. Place an index.html in the directory passed to --assets
  2. Copy the complete dufs frontend assets (including index.html) into the directory
  3. Verify you passed the UI assets dir, not the data/share root
  4. Re-run your frontend build if index.html failed to generate

Example fix

# before
dufs --assets ./data
# after
cp -r dist/* ./custom-assets/   # ensure custom-assets/index.html exists
dufs --assets ./custom-assets ./data
Defensive patterns

Strategy: validation

Validate before calling

#!/bin/sh
ASSETS_DIR=./custom-assets
[ -f "$ASSETS_DIR/index.html" ] || { echo "$ASSETS_DIR/index.html missing"; exit 1; }

Prevention

When it happens

Trigger: Running dufs with --assets <dir> where <dir> exists but has no index.html; pointing --assets at a data directory, an empty folder, or a partially copied frontend build.

Common situations: Custom UI overrides where only some files were copied into the assets dir; CI build step that didn't emit index.html; pointing --assets at the served data root instead of the UI directory.

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/dufs@fe7fd564f8 (2026-09-09). Data as JSON: /api/errors/2589add7404b3939. Report an issue: GitHub.

Appendix: source

Thrown at src/args.rs:476

    fn sanitize_path<P: AsRef<Path>>(path: P) -> Result<PathBuf> {
        let path = path.as_ref();
        if !path.exists() {
            bail!("Path `{}` doesn't exist", path.display());
        }

        env::current_dir()
            .and_then(|mut p| {
                p.push(path); // If path is absolute, it replaces the current path.
                std::fs::canonicalize(p)
            })
            .with_context(|| format!("Failed to access path `{}`", path.display()))
    }

    fn sanitize_assets_path<P: AsRef<Path>>(path: P) -> Result<PathBuf> {
        let path = Self::sanitize_path(path)?;
        if !path.join("index.html").exists() {
            bail!("Path `{}` doesn't contains index.html", path.display());
        }
        Ok(path)
    }
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum BindAddr {
    IpAddr(IpAddr),
    #[cfg(unix)]
    SocketPath(String),
}

impl BindAddr {
    fn parse_addrs(addrs: &[&str]) -> Result<Vec<Self>> {
        let mut bind_addrs = vec![];
        #[cfg(not(unix))]
        let mut invalid_addrs = vec![];
        for addr in addrs {

View on GitHub (pinned to fe7fd564f8)