jdx/mise · error

configuration disappeared from preview commit

Error message

configuration disappeared from preview commit

What it means

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.

Solutions

  1. Regenerate the preview (rerun onboarding) so ls_tree and object_at read the same consistent commit
  2. Run `git fsck --lost-found` in the preview/source repository to detect missing objects
  3. Verify the enrollment manifest matches the head commit; recompute or re-adopt history metadata if it is stale

Example fix

let Some((mode, oid)) = repo.object_at(&head, &entry.path)? else {
    bail!("configuration disappeared from preview commit");
};
// instead of ignoring the missing entry, refresh the preview store first:
// let (temp, preview) = preview_store(...)?; // rebuild from a fresh snapshot
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure every ls_tree entry of head resolves before previewing
for entry in repo.ls_tree(&head)? {
    if repo.object_at(&head, &entry.path)?.is_none() {
        return Err(format!("missing object for {} in preview commit", entry.path));
    }
}

Try / catch

match preview_configuration(&repo, &head, &encrypted) {
    Err(e) if e.to_string().contains("disappeared from preview commit") => {
        // rebuild the preview store and retry once
        let (temp, preview) = preview_store(&source)?;
        preview_configuration(preview.repo(), &head, &encrypted)
    }
    other => other,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/68fc25cdababdd51. Report an issue: GitHub.

Appendix: source

Thrown at src/system/history/sync/onboard.rs:98

    Ok((temp, preview))
}

fn preview_configuration(store: &Store) -> Result<tempfile::TempDir> {
    let temp = tempfile::tempdir()?;
    let repo = store
        .repo()
        .ok_or_else(|| eyre::eyre!("preview requires git"))?;
    let head = repo
        .ref_oid(UPSTREAM_REF)?
        .ok_or_else(|| eyre::eyre!("setup preview has no fetched branch"))?;
    let encrypted = super::files::encrypted_paths(repo, Some(&head))?;
    let tracked = crate::system::history::manifest::Manifest::read(repo, &head)?
        .ok_or_else(|| eyre::eyre!("setup repository has no enrollment metadata"))?
        .tracking()?;
    for entry in repo.ls_tree(&head)? {
        if let Some(relative) = preview_config_path(&tracked, &entry.path)? {
            let Some((mode, oid)) = repo.object_at(&head, &entry.path)? else {
                bail!("configuration disappeared from preview commit");
            };
            let (mode, oid) = if encrypted.contains(&entry.path) {
                super::files::decrypt(repo, &entry.path, &(mode, oid), true)?
            } else {
                (mode, oid)
            };
            crate::system::history::replay::write_path(
                repo,
                &temp.path().join(relative),
                &mode,
                &oid,
            )?;
        }
    }
    // Machine-local inputs are not published, but affect the real bootstrap.
    let local = global_config_dir().join("config.local.toml");
    if local.is_file() {
        std::fs::copy(local, temp.path().join("config.local.toml"))?;

View on GitHub (pinned to 533346cc37)