{"record":{"id":"b74fe10f1f15eb37","repo":"astrid-runtime/astrid","slug":"captured-version-chain-must-contain-at-least-two-r","errorCode":null,"errorMessage":"captured version chain must contain at least two readable versions","messagePattern":"captured version chain must contain at least two readable versions","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-storage-chunker-evidence/src/corpus.rs","lineNumber":122,"sourceCode":"                continue;\n            }\n            let object = format!(\"{revision}:{}\", relative_path.to_string_lossy());\n            let version = Command::new(\"git\")\n                .args([\"-C\"])\n                .arg(repository)\n                .args([\"show\", &object])\n                .output()\n                .context(\"read captured version\")?;\n            if !version.status.success() {\n                bail!(\n                    \"git could not read captured version: {}\",\n                    String::from_utf8_lossy(&version.stderr).trim()\n                );\n            }\n            inputs.push(memory(version.stdout));\n        }\n        if inputs.len() < 2 {\n            bail!(\"captured version chain must contain at least two readable versions\");\n        }\n        Self::from_files(name, CorpusKind::VersionChain, inputs)\n    }\n\n    pub fn synthetic_adversarial() -> Self {\n        let mebibyte = 1024 * 1024;\n        let inputs = vec![\n            memory(Vec::new()),\n            memory(vec![0x5a]),\n            memory(vec![0x7e; 4093]),\n            memory(vec![0; 8 * mebibyte]),\n            memory(vec![0xff; 8 * mebibyte]),\n            memory(periodic_bytes(8 * mebibyte)),\n            memory((0_u8..=u8::MAX).cycle().take(8 * mebibyte).collect()),\n            memory(b\"abcd\".repeat(2 * mebibyte)),\n            memory(pseudorandom_bytes(8 * mebibyte, 0x5eed_f00d_dead_beef)),\n            memory(boundary_pressure(8 * mebibyte)),\n        ];","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-storage-chunker-evidence/src/corpus.rs#L104-L140","documentation":"Version-chain corpora require at least two readable versions of a file to be meaningful for chunker comparison. After filtering revisions to those where the path actually exists and is readable, if fewer than two versions remain, `version_chain_from_git` bails with this error.","triggerScenarios":"Calling `version_chain_from_git` for a file whose history yields <2 readable versions: brand-new file with one commit, path with existence checks filtering out most revisions, or all `git show` reads failing.","commonSituations":"Pointing the corpus builder at a recently added file with a single commit; a file only present at HEAD after a rename history break; a shallow clone hiding older versions.","solutions":["Choose a file with a longer tracked history (at least two commits touching it).","Verify renames didn't break history (`git log --follow <path>`) and use the original path if needed.","Unshallow the clone so older revisions are available.","Fall back to a synthetic corpus if the target file's history is too short."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Count reachable revisions touching the path before building the corpus\nlet out = Command::new(\"git\").arg(\"-C\").arg(&repo)\n    .args([\"rev-list\", \"--count\", \"HEAD\", \"--\"]).arg(&path).output()?;\nassert!(String::from_utf8_lossy(&out.stdout).trim().parse::<u32>().unwrap_or(0) >= 2,\n    \"path needs >= 2 revisions\");","typeGuard":null,"tryCatchPattern":"match version_chain_from_git(&repo, &path, name) {\n    Err(e) if e.to_string().contains(\"at least two readable versions\") => {\n        // fall back to synthetic_adversarial() corpus or pick a longer-lived file\n    }\n    other => other,\n}","preventionTips":["Select corpus files with substantial tracked history (>= 2 commits)","Unshallow clones before version-chain generation","Account for renames: use `git log --follow` to pick the right path"],"tags":["git","corpus","version-chain","insufficient-data"],"backgroundTag":"empty-result-set","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}