{"record":{"id":"a65d363de1d18824","repo":"jdx/mise","slug":"transferred-revision-mismatch","errorCode":null,"errorMessage":"transferred revision mismatch","messagePattern":"transferred revision mismatch","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/remote_repository.rs","lineNumber":223,"sourceCode":"    let temporary = if dry_run {\n        tempfile::tempdir()?\n    } else {\n        tempfile::tempdir_in(parent)?\n    };\n    let checkout = temporary.path().join(\"checkout\");\n    let shown = crate::file::display_path(destination);\n    let mut command = Command::new(\"git\");\n    crate::git::sanitize_git_command(&mut command);\n    let output = command\n        .args([\"clone\", \"--no-checkout\", \"--\"])\n        .arg(bundle)\n        .arg(&checkout)\n        .output()?;\n    if !output.status.success() {\n        bail!(\"invalid transferred repository bundle\");\n    }\n    if git(&checkout, &[\"rev-parse\", \"HEAD\"])? != revision {\n        bail!(\"transferred revision mismatch\");\n    }\n    let entries = git(&checkout, &[\"ls-tree\", \"-r\", \"-z\", \"--name-only\", revision])?;\n    for entry in entries.split('\\0').filter(|s| !s.is_empty()) {\n        let path = Path::new(entry);\n        if path\n            .components()\n            .any(|c| !matches!(c, std::path::Component::Normal(_)))\n            || entry.split('/').any(|p| p.eq_ignore_ascii_case(\".git\"))\n        {\n            bail!(\"unsafe source repository path\");\n        }\n        if entry.to_ascii_lowercase().ends_with(\".local.toml\") {\n            bail!(\n                \"source contains machine-local configuration ({entry}); remove it from the repository before onboarding\"\n            );\n        }\n    }\n    git(&checkout, &[\"remote\", \"set-url\", \"origin\", origin])?;","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/jdx/mise/blob/afd2eddd3a50c16190efc1c7e94404b48f72af57/src/system/remote_repository.rs#L205-L241","documentation":"After unpacking the bundle and cloning it, install_at compares `git rev-parse HEAD` in the checkout against the requested revision. A mismatch means the bundle's tip differs from the pinned commit, so the install aborts to guarantee the installed files exactly match the pinned revision.","triggerScenarios":"install_at given revision R while the bundle's HEAD resolves to a different commit — bundle generated from another commit, force-push rewrote history, or stale bundle.","commonSituations":"Repo history rewritten between fetch and install; mixing a cached bundle with a newer pinned revision; typo'd SHA from a different repo.","solutions":["Re-fetch so the bundle contains exactly the pinned revision at its tip","Use the revision that the bundle actually contains (read HEAD from the checkout)","Purge cached bundles and repeat the full fetch/install cycle"],"exampleFix":"// before\ninstall_at(origin, old_rev, ...); // old_rev no longer matches bundle HEAD\n// after\nlet rev = fetch_bundle_head(origin);\ninstall_at(origin, &rev, ...);","handlingStrategy":"retry","validationCode":"// preflight: confirm the revision is the repository's current tip\n// $ git ls-remote <origin> refs/heads/<branch>  # compare against pinned rev","typeGuard":null,"tryCatchPattern":"match install_at(origin, &rev, dest) {\n    Err(e) if e.to_string().contains(\"transferred revision mismatch\") => {\n        let fresh = resolve_current_tip(origin)?;\n        install_at(origin, &fresh, dest)\n    }\n    other => other,\n}","preventionTips":["Re-pin to the latest tip right before install if history may have been rewritten","Avoid force-pushes on onboarding source branches","Always pair a fresh fetch with a fresh revision"],"tags":["git","integrity","revision"],"backgroundTag":"checksum-mismatch","analyzedSha":"afd2eddd3a50c16190efc1c7e94404b48f72af57","analyzedAt":"2026-09-09T01:38:25.179Z","contentChangedAt":"2026-09-09T01:38:25.179Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}