jdx/mise · error

incoming setup is missing required source {}

Error message

incoming setup is missing required source {}

What it means

Every required source must either exist in the incoming write set, exist on local disk, or have some incoming child write under it (a directory-style source with children being written). If none of these hold — the incoming batch has no plan touching the path, the file is not on disk, and no incoming child covers it — mise cannot satisfy the declared source requirement and aborts.

Source

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

        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)
            && roots
                .locate(&plan.branch_path)
                .path()
                .is_some_and(|p| p.starts_with(path))
    })

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. Add the missing source file to the shared repository (or to a path with incoming children) and pull.
  2. Update the local tracked set/declarations to drop the stale required-source entry if it is no longer needed.
  3. Run the pull/reconcile step so the batch includes the missing source before applying.

Example fix

// before: repo has no .mise/sources/shellrc but tracked set requires it
// after
cp ~/.templates/shellrc .mise/sources/shellrc && git add .mise/sources/shellrc && git commit -m "add required source"
Defensive patterns

Strategy: validation

Validate before calling

for (const src of tracked.requiredSources) {
  if (!planCovers(src) && !fs.existsSync(src) && !hasIncomingChild(src)) {
    throw new Error(`required source missing from batch and disk: ${src}`);
  }
}

Type guard

const sourceAvailable = (src) => planCovers(src) || fs.existsSync(src);

Try / catch

try {
  await applyIncoming();
} catch (e) {
  if (String(e.message).startsWith("incoming setup is missing required source")) {
    console.error("Add the source to the shared repo or drop the stale declaration, then pull.");
  } else throw e;
}

Prevention

When it happens

Trigger: In `sources`, the plan list contains no entry for a required source path (`None` arm), the path does not exist locally (`!source.exists()`), and `has_incoming_child` finds no incoming write under it. Triggered when the shared repo never provided a source that the local tracked set declares as required.

Common situations: A new machine enrolls into a repo whose current commit lacks a source file that an older tracked set expects; the source was renamed upstream while this machine still references the old path; partial clone/checkout missing the file.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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