jdx/mise · error

required source is not a regular file: {}

Error message

required source is not a regular file: {}

What it means

The sync batch declares certain files as required sources (inputs that other managed files are derived from or depend on). Before applying, mise verifies each required source is available as a regular file in the incoming write set. If the incoming tree entry exists but has a non-regular git mode (symlink, submodule, etc.), mise bails because a required input must be a real, readable file blob.

Source

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

    // The repository inventory, not a source or output mentioned by incoming
    // configuration, determines which files the batch may install.
    let mut prospective = tracked.clone();
    prospective.required_sources = declarations.required_sources;
    Ok(prospective)
}

/// 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 => {}
        }

View on GitHub (pinned to afd2eddd3a)

Solutions

  1. In the shared repo, replace the symlink/submodule at the source path with a real regular file and commit.
  2. If the source intentionally lives elsewhere, copy its content into the repository at the required path.
  3. Remove the file from the required-sources declarations if it is no longer a genuine input.

Example fix

// before
ln -s ../../../templates/shellrc .mise/sources/shellrc && git add .mise/sources/shellrc  # 120000
// after
cp ../../../templates/shellrc .mise/sources/shellrc && git add .mise/sources/shellrc      # 100644
Defensive patterns

Strategy: validation

Validate before calling

const entry = planFor(sourcePath)?.apply;
if (entry && entry.mode !== "100644" && entry.mode !== "100755") {
  throw new Error(`required source must be a regular file: ${sourcePath}`);
}

Type guard

const isRegularEntry = (e) => e != null && (e.mode === "100644" || e.mode === "100755");

Try / catch

try {
  await applyIncoming();
} catch (e) {
  if (String(e.message).startsWith("required source is not a regular file")) {
    console.error("Commit the source as a real file in the shared repo, not a symlink/submodule.");
  } else throw e;
}

Prevention

When it happens

Trigger: In `sources`, a required source path matches a plan whose apply entry is `Some(Some((mode, oid)))` with mode not in {100644, 100755}. Triggered when a required source file was committed as a symlink (120000) or submodule (160000) in the incoming branch.

Common situations: Someone symlinked a template/source file into the repo instead of copying it; a source path became a submodule after a refactor; legacy repo content contains gitlinks where blobs are expected.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


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