jdx/mise · error

files: {}

Error message

files: {}

What it means

Aggregate error raised while building an apply plan: one or more `[files]` entries failed validation, and the per-entry problem lines are joined and prefixed with "files: ". Each problem line names the failing entry and its underlying error.

Source

Thrown at src/system/files.rs:2250

            missing_sources.join("\n")
        ));
    }
    if !broken.is_empty() {
        problems.push(format!("entries with errors:\n{}", broken.join("\n")));
    }
    if !conflicts.is_empty() && !opts.force {
        problems.push(format!(
            "refusing to overwrite existing files ({}):\n{}",
            opts.force_hint,
            conflicts
                .iter()
                .map(|p| format!("  {}", p.display_user()))
                .collect::<Vec<_>>()
                .join("\n")
        ));
    }
    if !problems.is_empty() {
        bail!("files: {}", problems.join("\nfiles: "));
    }
    Ok(ApplyPlan {
        todo,
        record_symlink_each,
        reconciliation: plan_symlink_each_reconciliation(active_requests, requests)?,
    })
}

fn cleanup_reconciled_directories(reconciliation: &SymlinkEachReconciliation) -> Result<()> {
    for target in &reconciliation.targets {
        for start in reconciliation
            .stale_links
            .iter()
            .filter(|link| link.target.starts_with(target))
            .filter_map(|link| link.target.parent())
            .sorted_by_key(|path| std::cmp::Reverse(path.components().count()))
            .unique()
        {

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Read each problem line in the message; it names the `[files]` entry (by target) and the underlying error.
  2. Fix the referenced config entry in mise.toml (source path, target path).
  3. Re-run after all listed entries validate.

Example fix

// before (mise.toml)
[[files]]
source = "~/dotfiles/vimrc"
target = "~/.vimrc"  # ~/dotfiles/vimrc was deleted

// after
# restore the file in the repo or remove the [[files]] entry
[[files]]
source = "~/dotfiles/vimrc"
target = "~/.vimrc"
Defensive patterns

Strategy: validation

Validate before calling

fn validate_files_entries(config: &toml::Value) -> anyhow::Result<()> {
    if let Some(entries) = config.get("files").and_then(|f| f.as_array()) {
        for e in entries {
            let source = e.get("source").and_then(|s| s.as_str())
                .ok_or_else(|| anyhow::anyhow!("[[files]] entry missing source"))?;
            if !std::path::Path::new(shellexpand::tilde(source).as_ref()).exists() {
                anyhow::anyhow::bail!("[[files]] source does not exist: {source}");
            }
        }
    }
    Ok(())
}

Try / catch

match result {
    Err(e) if e.to_string().starts_with("files: ") => {
        eprintln!("Fix each listed [files] entry in mise.toml:\n{e}");
    }
    Err(e) => return Err(e),
    Ok(plan) => apply(plan),
}

Prevention

When it happens

Trigger: Calling the files apply/planning API when any dotfiles entry has a validation problem (missing source, invalid target, unreadable path, etc.); problems collected during plan construction are non-empty.

Common situations: A config entry references a deleted source file, a target path with wrong type, or another per-entry error surfaced during validation before anything is applied.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/804497592c996899. Report an issue: GitHub.