{"record":{"id":"e352d14994bf8ec2","repo":"GitoxideLabs/gitoxide","slug":"could-not-read-reference-err-e352d1","errorCode":null,"errorMessage":"could not read reference: {err}","messagePattern":"could not read reference: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gix-tix/src/history.rs","lineNumber":1277,"sourceCode":"    revisions: &[OsString],\n    hidden: &[OsString],\n    include_worktrees: bool,\n) -> Result<RefSnapshot> {\n    snapshot_ignoring_pin(repo, revisions, hidden, include_worktrees, None)\n}\n\npub(crate) fn ref_tree_revisions(repo: &gix::Repository, include_tags: bool) -> Result<Vec<OsString>> {\n    let mut out = Vec::new();\n    for reference in repo\n        .references()\n        .context(\"could not open references\")?\n        .all()\n        .context(\"could not iterate references\")?\n    {\n        let mut reference = match reference {\n            Ok(reference) => reference,\n            Err(err) if is_missing_ref(&*err) => continue,\n            Err(err) => return Err(anyhow::anyhow!(\"could not read reference: {err}\")),\n        };\n        let name = reference.name().as_bstr().to_owned();\n        let kind = decoration_kind(&name);\n        if matches!(kind, DecorationKind::Special | DecorationKind::Pin)\n            || matches!(kind, DecorationKind::Tag) && !include_tags\n            || name.starts_with(STASH_PREFIX)\n            || name.starts_with(REVIEW_STASH_PREFIX)\n        {\n            continue;\n        }\n        let Ok(id) = reference.peel_to_id() else { continue };\n        if repo.find_header(id)?.kind() != gix::object::Kind::Commit {\n            continue;\n        }\n        out.push(gix::path::from_bstr(&name).into_owned().into_os_string());\n    }\n    if repo.head().is_ok_and(|head| head.referent_name().is_none()) {\n        out.push(\"HEAD\".into());","sourceCodeStart":1259,"sourceCodeEnd":1295,"githubUrl":"https://github.com/GitoxideLabs/gitoxide/blob/e73179060badf27222d790981fac3f84c1830a7e/gix-tix/src/history.rs#L1259-L1295","documentation":"When collecting reference decorations for history, tix iterates all references in the repository. Most errors reading an individual ref are skipped only if they indicate the ref went missing mid-iteration; any other failure is wrapped as `could not read reference: {err}` and aborts the decoration pass.","triggerScenarios":"Calling the all-references iteration API (history decoration collection, around history.rs:1277) when the refs iterator returns an `Err` that is not a missing-ref condition — e.g. an unreadable loose ref, corrupt packed-refs entry, or permission error on any ref including tags and remote branches.","commonSituations":"Concurrent ref updates corrupting loose refs during iteration, restricted filesystem permissions, damaged packed-refs, or a repository on a flaky network mount.","solutions":["Run `git fsck` and inspect `.git/refs` / `.git/packed-refs` for corruption","Fix permissions on the `.git` directory and ref files","Stop concurrent git/tix processes that may be rewriting refs, then retry","Identify the specific failing ref from the wrapped error and repair or delete it"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// sanity-check all refs are readable before decoration pass\nlet output = std::process::Command::new(\"git\")\n    .args([\"for-each-ref\", \"--format=%(refname)\"])\n    .output()\n    .expect(\"run git\");\nassert!(output.status.success(), \"refs unreadable: {}\", String::from_utf8_lossy(&output.stderr));","typeGuard":"fn is_benign_ref_error(err: &dyn std::error::Error) -> bool {\n    err.to_string().to_lowercase().contains(\"not found\")\n}","tryCatchPattern":"match collect_ref_decorations(&repo, include_tags) {\n    Ok(decorations) => decorations,\n    Err(e) if e.to_string().starts_with(\"could not read reference\") => {\n        eprintln!(\"a ref is unreadable: {e}\");\n        repair_refs(&repo)?;\n        collect_ref_decorations(&repo, include_tags)?\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Avoid concurrent ref-mutating processes during history rendering","Repair packed-refs corruption with `git pack-refs --all` after backup","Keep repository on a local filesystem, not a flaky network mount","Audit `.git/refs` permissions when errors mention access"],"tags":["git","refs","decoration","io"],"backgroundTag":"git-command-failed","analyzedSha":"e73179060badf27222d790981fac3f84c1830a7e","analyzedAt":"2026-09-08T11:26:50.865Z","contentChangedAt":"2026-09-08T11:26:50.865Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}