sigoden/dufs · error · anyhow::Error

Invalid auth value ` : @

Error message

Invalid auth value `{user}:{pass}@{paths}

What it means

`Auth::new` parses `user:pass@paths` auth entries and merges the paths portion via `AccessPaths::merge`. When that merge fails (unparseable path rules), construction aborts and the full offending `user:pass@paths` value is echoed so the bad part can be located. This prevents starting with silently-wrong per-user permissions.

Solutions

  1. Verify the section after `@` is a valid path spec such as `/:rw` or `/:` (read-only default).
  2. Quote the entire `--auth` argument in the shell.
  3. Check the `AccessPaths::merge` implementation for exactly which strings are accepted.
  4. Split complicated multi-path rules across separate `--auth` flags.

Example fix

// before
--auth admin:secret@:w   (invalid perm/path spec)
// after
--auth admin:secret@/:rw
Defensive patterns

Strategy: validation

Validate before calling

fn check_auth_entry(entry: &str) -> Result<(), String> {
    let (creds, paths) = entry.split_once('@').ok_or("missing @paths")?;
    if creds.is_empty() || !creds.contains(':') || paths.is_empty() { return Err(format!("bad entry {}", entry)); }
    Ok(())
}

Prevention

When it happens

Trigger: Any `--auth user:pass@<paths>` value whose `<paths>` section cannot be parsed by `AccessPaths::merge` (empty paths, unknown rule characters, malformed `path:perm` entries).

Common situations: Copy-pasting auth strings with stray whitespace or smart quotes; forgetting the path part after `@`; using permission letters other than r/w; shell glob expansion altering the value.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of sigoden/dufs@fe7fd564f8 (2026-09-09). Data as JSON: /api/errors/45aa8d8a25ad0292. Report an issue: GitHub.

Appendix: source

Thrown at src/auth.rs:88

                    bail!("Invalid auth `{rule}`");
                }
                account_paths_pairs.push((user, pass, paths));
            }
        }
        let mut anonymous = None;
        if let Some(paths) = annoy_paths {
            let mut access_paths = AccessPaths::default();
            access_paths
                .merge(paths)
                .ok_or_else(|| anyhow!("Invalid auth value `@{paths}"))?;
            anonymous = Some(access_paths);
        }
        let mut users = IndexMap::new();
        for (user, pass, paths) in account_paths_pairs.into_iter() {
            let mut access_paths = AccessPaths::default();
            access_paths
                .merge(paths)
                .ok_or_else(|| anyhow!("Invalid auth value `{user}:{pass}@{paths}"))?;
            if let Some(anon_ap) = &anonymous {
                let orig_user = access_paths.clone();
                access_paths.absorb_anon(
                    anon_ap,
                    &orig_user,
                    AccessPerm::IndexOnly,
                    AccessPerm::IndexOnly,
                );
            }
            if pass.starts_with("$6$") {
                use_hashed_password = true;
            }
            users.insert(user.to_string(), (pass.to_string(), access_paths));
        }

        Ok(Self {
            empty: false,
            use_hashed_password,

View on GitHub (pinned to fe7fd564f8)