{"record":{"id":"4396fca26c1dc249","repo":"jdx/mise","slug":"incoming-setup-is-missing-required-source","errorCode":null,"errorMessage":"incoming setup is missing required source {}","messagePattern":"incoming setup is missing required source (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/sync/preflight.rs","lineNumber":154,"sourceCode":"        let planned = plans\n            .iter()\n            .find(|plan| roots.locate(&plan.branch_path).path() == Some(source.as_path()));\n        match planned.and_then(|plan| plan.apply.as_ref()) {\n            Some(Some((mode, oid))) => {\n                if mode != \"100644\" && mode != \"100755\" {\n                    bail!(\n                        \"required source is not a regular file: {}\",\n                        source.display()\n                    );\n                }\n                repo.cat_object(oid)?;\n            }\n            Some(None) => bail!(\n                \"incoming setup deletes required source {}\",\n                source.display()\n            ),\n            None if !source.exists() && !has_incoming_child(&roots, source, plans) => {\n                bail!(\n                    \"incoming setup is missing required source {}\",\n                    source.display()\n                );\n            }\n            None => {}\n        }\n    }\n    Ok(())\n}\n\nfn has_incoming_child(roots: &Roots, path: &Path, plans: &[PathPlan]) -> bool {\n    plans.iter().any(|plan| {\n        plan.apply.as_ref().is_some_and(Option::is_some)\n            && roots\n                .locate(&plan.branch_path)\n                .path()\n                .is_some_and(|p| p.starts_with(path))\n    })","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/history/sync/preflight.rs#L136-L172","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Add the missing source file to the shared repository (or to a path with incoming children) and pull.","Update the local tracked set/declarations to drop the stale required-source entry if it is no longer needed.","Run the pull/reconcile step so the batch includes the missing source before applying."],"exampleFix":"// before: repo has no .mise/sources/shellrc but tracked set requires it\n// after\ncp ~/.templates/shellrc .mise/sources/shellrc && git add .mise/sources/shellrc && git commit -m \"add required source\"","handlingStrategy":"validation","validationCode":"for (const src of tracked.requiredSources) {\n  if (!planCovers(src) && !fs.existsSync(src) && !hasIncomingChild(src)) {\n    throw new Error(`required source missing from batch and disk: ${src}`);\n  }\n}","typeGuard":"const sourceAvailable = (src) => planCovers(src) || fs.existsSync(src);","tryCatchPattern":"try {\n  await applyIncoming();\n} catch (e) {\n  if (String(e.message).startsWith(\"incoming setup is missing required source\")) {\n    console.error(\"Add the source to the shared repo or drop the stale declaration, then pull.\");\n  } else throw e;\n}","preventionTips":["When enrolling a new machine, ensure the repo commit includes every declared required source.","Update tracked declarations in the same commit that renames/removes source files.","Run the reconcile step fully before applying so all sources are included in the batch."],"tags":["git","sync","missing-file","state-consistency"],"backgroundTag":"file-not-found","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}