jdx/mise · error

incoming setup deletes required source {}

Error message

incoming setup deletes required source {}

What it means

A required source file must be available either in the incoming write set or already locally. If the incoming batch explicitly deletes the path (its plan apply is `Some(None)`, i.e. a queued deletion), mise refuses to proceed: a queued deletion is not an available source, and applying the batch would leave the tracked set referencing a missing input.

Source

Thrown at src/system/history/sync/preflight.rs:149

/// Required source files must exist in the complete proposed write set or
/// already be available locally. A queued deletion is not an available source.
pub(super) fn sources(repo: &HistoryRepo, tracked: &TrackedSet, plans: &[PathPlan]) -> Result<()> {
    let roots = Roots::current();
    for source in &tracked.required_sources {
        let planned = plans
            .iter()
            .find(|plan| roots.locate(&plan.branch_path).path() == Some(source.as_path()));
        match planned.and_then(|plan| plan.apply.as_ref()) {
            Some(Some((mode, oid))) => {
                if mode != "100644" && mode != "100755" {
                    bail!(
                        "required source is not a regular file: {}",
                        source.display()
                    );
                }
                repo.cat_object(oid)?;
            }
            Some(None) => bail!(
                "incoming setup deletes required source {}",
                source.display()
            ),
            None if !source.exists() && !has_incoming_child(&roots, source, plans) => {
                bail!(
                    "incoming setup is missing required source {}",
                    source.display()
                );
            }
            None => {}
        }
    }
    Ok(())
}

fn has_incoming_child(roots: &Roots, path: &Path, plans: &[PathPlan]) -> bool {
    plans.iter().any(|plan| {
        plan.apply.as_ref().is_some_and(Option::is_some)

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Restore the deleted source file in the shared repository (git revert the deletion or re-add the content).
  2. If the source is genuinely obsolete, first update/remove the declarations that require it (in the tracked set / config), commit, then pull.
  3. Re-run the sync after pulling a branch where the source exists.

Example fix

// before (incoming commit)
git rm .mise/sources/shellrc   # still required by tracked set
// after
git checkout HEAD~1 -- .mise/sources/shellrc && git commit -m "restore required source"  # or update dependents first
Defensive patterns

Strategy: validation

Validate before calling

for (const src of tracked.requiredSources) {
  const plan = planFor(src);
  if (plan && plan.apply === null) {
    throw new Error(`incoming batch deletes required source: ${src}`);
  }
}

Try / catch

try {
  await applyIncoming();
} catch (e) {
  if (String(e.message).startsWith("incoming setup deletes required source")) {
    console.error("Restore the source or update dependent declarations before syncing.");
  } else throw e;
}

Prevention

When it happens

Trigger: In `sources`, the plan for a required-source path has `apply == Some(None)` — the incoming repository records a deletion of that file while the current tracked set still lists it as a required source (e.g. a template consumed to render a managed file).

Common situations: A teammate deleted a template/source file that other machines' tracked sets still depend on; a rename in the repo removed the old path without updating dependent declarations; a branch reverted the addition of the source file.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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