jdx/mise · error

brew-cask: generic artifact source has no filename

Error message

brew-cask: generic artifact source has no filename

What it means

During a trusted generic-artifact rename/backup, mise extracts the file-name component of the source path; if the path has no file name (it is a filesystem root or ends with no name component), the operation cannot proceed and mise returns this eyre error. A path without a filename cannot be renamed within its parent, so the backend fails fast.

Solutions

  1. Fix the artifact record so it contains a concrete file path with a name component, not a root path.
  2. Check your prefix configuration — a prefix of '/' will make artifact paths resolve to root; use a real prefix directory.
  3. Reinstall the cask to regenerate valid target records.
  4. Inspect and prune stale/corrupted target records left by an earlier mise or prefix layout.

Example fix

// before (corrupted record)
record.path = "/"
// after (valid record)
record.path = "/opt/homebrew/share/mytool/data.bin"
Defensive patterns

Strategy: validation

Validate before calling

if src.file_name().is_none() {
    eprintln!("source path must include a file name, got: {}", src.display());
    std::process::exit(1);
}

Type guard

fn has_filename(p: &std::path::Path) -> bool {
    p.file_name().is_some()
}

Prevention

When it happens

Trigger: rename_trusted_generic_target receives a source path like '/' or a path whose file_name() is None (trailing-root path); an artifact record containing a root or empty path; corrupted target records from a previous install.

Common situations: Corrupted or hand-edited artifact target records containing '/' or empty strings; prefix set to '/' so artifact paths resolve to root; migration bugs producing malformed recorded paths.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/5ae0493f2306bf1c. Report an issue: GitHub.

Appendix: source

Thrown at src/system/packages/brew/cask/mod.rs:2576

            .ok_or_else(|| eyre!("brew-cask: generic artifact target has no filename"))?;
        nix::fcntl::renameat(&parent.fd, from_name, &parent.fd, to_name)?;
        Ok(())
    }
    #[cfg(not(unix))]
    {
        let _ = expected_parent;
        file::rename(from, to)
    }
}

fn ditto(from: &Path, to: &Path) -> Result<()> {
    let status = std::process::Command::new("ditto")
        .arg(from)
        .arg(to)
        .status()
        .wrap_err("failed to run ditto")?;
    if !status.success() {
        bail!(
            "ditto failed copying {} to {}",
            from.display(),
            to.display()
        );
    }
    Ok(())
}

/// Run a helper with its working directory bound to `dir` via `fchdir`, so
/// relative arguments resolve from that exact directory inode.
///
/// Passing a pathname to a subprocess would let it re-resolve every component,
/// which a same-uid replacement can redirect. `fchdir` in the child pins
/// resolution to the descriptor mise already verified, so relative names cannot
/// escape the validated application directory.
#[cfg(unix)]
fn run_in_trusted_dir<Fd: std::os::fd::AsFd>(
    program: &str,

View on GitHub (pinned to 533346cc37)