{"record":{"id":"68fc25cdababdd51","repo":"jdx/mise","slug":"configuration-disappeared-from-preview-commit","errorCode":null,"errorMessage":"configuration disappeared from preview commit","messagePattern":"configuration disappeared from preview commit","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/history/sync/onboard.rs","lineNumber":98,"sourceCode":"    Ok((temp, preview))\n}\n\nfn preview_configuration(store: &Store) -> Result<tempfile::TempDir> {\n    let temp = tempfile::tempdir()?;\n    let repo = store\n        .repo()\n        .ok_or_else(|| eyre::eyre!(\"preview requires git\"))?;\n    let head = repo\n        .ref_oid(UPSTREAM_REF)?\n        .ok_or_else(|| eyre::eyre!(\"setup preview has no fetched branch\"))?;\n    let encrypted = super::files::encrypted_paths(repo, Some(&head))?;\n    let tracked = crate::system::history::manifest::Manifest::read(repo, &head)?\n        .ok_or_else(|| eyre::eyre!(\"setup repository has no enrollment metadata\"))?\n        .tracking()?;\n    for entry in repo.ls_tree(&head)? {\n        if let Some(relative) = preview_config_path(&tracked, &entry.path)? {\n            let Some((mode, oid)) = repo.object_at(&head, &entry.path)? else {\n                bail!(\"configuration disappeared from preview commit\");\n            };\n            let (mode, oid) = if encrypted.contains(&entry.path) {\n                super::files::decrypt(repo, &entry.path, &(mode, oid), true)?\n            } else {\n                (mode, oid)\n            };\n            crate::system::history::replay::write_path(\n                repo,\n                &temp.path().join(relative),\n                &mode,\n                &oid,\n            )?;\n        }\n    }\n    // Machine-local inputs are not published, but affect the real bootstrap.\n    let local = global_config_dir().join(\"config.local.toml\");\n    if local.is_file() {\n        std::fs::copy(local, temp.path().join(\"config.local.toml\"))?;","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/jdx/mise/blob/533346cc374382b41ec5ff70536252b2e96e725c/src/system/history/sync/onboard.rs#L80-L116","documentation":"preview_configuration walks the preview commit's tree to reconstruct configuration entries, decrypting encrypted files that are part of configuration. For each tracked config path it re-resolves the blob via object_at; if the path was listed by ls_tree but the object lookup returns None, the commit tree is inconsistent with the index/manifest and the library bails rather than producing a wrong preview.","triggerScenarios":"Calling preview_configuration (via run, or the preview_does_not_decrypt_encrypted_files_outside_configuration test) when repo.object_at(head, path) returns None for a path that ls_tree(&head) just listed — e.g. the manifest/tracking metadata is stale relative to the tree, or the repository lost objects between the two reads.","commonSituations":"Race where the preview repository is mutated concurrently between ls_tree and object_at; corrupted or pruned git objects (partial clone / gc during preview); manifest tracking set disagreeing with the actual commit tree after a hand-repaired repo.","solutions":["Regenerate the preview (rerun onboarding) so ls_tree and object_at read the same consistent commit","Run `git fsck --lost-found` in the preview/source repository to detect missing objects","Verify the enrollment manifest matches the head commit; recompute or re-adopt history metadata if it is stale"],"exampleFix":"let Some((mode, oid)) = repo.object_at(&head, &entry.path)? else {\n    bail!(\"configuration disappeared from preview commit\");\n};\n// instead of ignoring the missing entry, refresh the preview store first:\n// let (temp, preview) = preview_store(...)?; // rebuild from a fresh snapshot","handlingStrategy":"try-catch","validationCode":"// ensure every ls_tree entry of head resolves before previewing\nfor entry in repo.ls_tree(&head)? {\n    if repo.object_at(&head, &entry.path)?.is_none() {\n        return Err(format!(\"missing object for {} in preview commit\", entry.path));\n    }\n}","typeGuard":null,"tryCatchPattern":"match preview_configuration(&repo, &head, &encrypted) {\n    Err(e) if e.to_string().contains(\"disappeared from preview commit\") => {\n        // rebuild the preview store and retry once\n        let (temp, preview) = preview_store(&source)?;\n        preview_configuration(preview.repo(), &head, &encrypted)\n    }\n    other => other,\n}","preventionTips":["Never mutate the preview repository between ls_tree and object_at reads","Verify manifest tracking metadata matches the head commit before previewing","Detect object-store corruption early with `git fsck` after any repair or partial clone"],"tags":["git","history-sync","consistency"],"backgroundTag":"internal-invariant-violation","analyzedSha":"533346cc374382b41ec5ff70536252b2e96e725c","analyzedAt":"2026-09-17T13:35:38.149Z","contentChangedAt":"2026-09-17T13:35:38.149Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}