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
- 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
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
- 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
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
- cannot onboard this setup repository: history is unavailable
- could not snapshot the local history repository for preview
- forced publication is not supported
- incoming configuration must be a regular file
- incoming setup deletes required source
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)