jdx/mise · error · eyre::Report

source is missing; use --force to remove the target

Error message

source is missing; use --force to remove the target

What it means

Template entries verify their targets by rendering the source file, so the source must exist. If it is gone, verification is impossible and unapply refuses. `--dry-run` stays inert (it marks the removal conditional instead of rendering) and `--force` skips verification entirely.

Source

Thrown at src/system/files.rs:1614

            plan_single_file(req, opts, &mut paths)?;
        }
        FileMode::SymlinkEach => {
            bail!("mode symlink-each requires the source to be a directory");
        }
        FileMode::Template => {
            if !req.target.exists() && !req.target.is_symlink() {
                return Ok(None);
            }
            if opts.force {
                paths.insert(req.target.clone(), ());
            } else if opts.dry_run {
                // Rendering may execute commands. Keep dry-run inert, matching
                // apply/status policy, and describe the removal as conditional.
                paths.insert(req.target.clone(), ());
                conditional = true;
            } else {
                if !req.source.exists() {
                    bail!("source is missing; use --force to remove the target");
                }
                // Rendering may execute user-authored commands. Defer it until
                // after the complete unapply plan has been confirmed.
                conditional = true;
            }
        }
    }
    if paths.is_empty() && !cleanup_empty_dirs && !conditional && !clear_symlink_each_state {
        Ok(None)
    } else {
        Ok(Some(UnapplyPlan {
            req,
            paths: paths.into_keys().collect(),
            cleanup_empty_dirs,
            conditional,
            clear_symlink_each_state,
        }))
    }

View on GitHub (pinned to 6f52dcdf99)

Solutions

  1. Restore the template source or fix its `source` path in mise.toml, then unapply
  2. Use `--force` when you simply want the rendered target gone and verification is unnecessary
  3. Use `--dry-run` first to see the conditional removal plan

Example fix

# before: template renamed without updating config
$ ls ~/dotfiles/gitconfig.tmpl
ls: cannot access '~/dotfiles/gitconfig.tmpl': No such file or directory
$ mise bootstrap dotfiles unapply
Error: source is missing; use --force to remove the target

# after: update the path, then unapply verifies via render
$ sed -i 's/gitconfig.tmpl/gitconfig.tera/' mise.toml
$ mise bootstrap dotfiles unapply
Defensive patterns

Strategy: validation

Validate before calling

# Template sources must exist before an unapply is attempted.
for t in ~/dotfiles/*.tmpl ~/dotfiles/*.tera; do
  [ -e "$t" ] || { echo "missing template source: $t"; exit 1; }
done

Type guard

fn is_missing_template_source(err: &miette::Report) -> bool {
    err.to_string()
        .starts_with("source is missing; use --force to remove the target")
}

Prevention

When it happens

Trigger: `unapply` of a `mode = "template"` entry where the target exists, `--force` and `--dry-run` are absent, and `!req.source.exists()` — the template file was deleted/moved or its path in mise.toml is a typo.

Common situations: Renamed the .tmpl file in the dotfiles repo without updating mise.toml; partial clone of the repo; typo in the source path.

Related errors


AI-assisted analysis of jdx/mise@6f52dcdf99 (2026-08-22). Data as JSON: /api/errors/e66897591b2e5ef6. Report an issue: GitHub.