can1357/oh-my-pi · error · Error

object not found: {spec}

Error message

object not found: {spec}

What it means

Error::ObjectNotFound is raised when a revision or object lookup fails — a `rev-parse`-style spec, a blob path, or a tree entry could not be resolved to an object in the repository database. Unlike RefNotFound, this covers any object spec (SHAs, ranges, path@rev), not just named refs.

Source

Thrown at crates/pi-vcs/src/error.rs:31

#[derive(Debug, thiserror::Error)]
pub enum Error {
	/// The directory is not inside a git repository / jj workspace.
	#[error("not a repository: {path}")]
	NotARepository {
		/// Directory the lookup started from.
		path: PathBuf,
	},

	/// A named ref (branch, tag, `refs/...`) does not exist.
	#[error("reference not found: {name}")]
	RefNotFound {
		/// The ref name as given by the caller.
		name: String,
	},

	/// A revision/object lookup failed (`rev-parse` style spec, blob path,
	/// tree).
	#[error("object not found: {spec}")]
	ObjectNotFound {
		/// The revision or object spec as given by the caller.
		spec: String,
	},

	/// Cherry-picking `sha` produced an empty commit (already applied or
	/// auto-resolved to HEAD). Callers should skip and continue the range —
	/// replaces the historical `/the previous cherry-pick is now empty/` stderr
	/// regex.
	#[error("cherry-pick of {sha} is empty")]
	EmptyCherryPick {
		/// The commit that collapsed to a no-op.
		sha: String,
	},

	/// A merge-style operation (cherry-pick, stash pop, 3-way apply) hit
	/// conflicting changes.
	#[error("merge conflict in {} file(s)", paths.len())]

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify the spec with `git rev-parse --verify <spec>^{object}` before calling the API.
  2. Unshallow the clone if the object predates the shallow boundary: `git fetch --unshallow`.
  3. List the tree at the commit (`git ls-tree <rev>`) to confirm the exact blob path.
  4. If the SHA came from external output, re-fetch the source repo or use the ref name instead of the (rewritten) SHA.

Example fix

// before
let blob = repo.read_blob("a1b2c3", "src/config.json")?; // path absent at that rev
// after
let commit = repo.resolve("a1b2c3")?;
let blob = match repo.read_blob(commit, "src/config.json") {
    Ok(b) => b,
    Err(Error::ObjectNotFound { .. }) => repo.read_blob("HEAD", "src/config.json")?,
    Err(e) => return Err(e),
};
Defensive patterns

Strategy: validation

Validate before calling

fn object_exists(repo: &pi_vcs::Vcs, spec: &str) -> bool {
    repo.resolve(spec).is_ok()
}
// for blob paths, check the tree first:
fn blob_exists_at(repo: &pi_vcs::Vcs, rev: &str, path: &str) -> bool {
    repo.list_tree(rev).map(|t| t.iter().any(|e| e.path == path)).unwrap_or(false)
}

Type guard

fn is_object_not_found(err: &pi_vcs::Error) -> bool {
    matches!(err, pi_vcs::Error::ObjectNotFound { .. })
}

Try / catch

match repo.read_blob(rev, path) {
    Err(pi_vcs::Error::ObjectNotFound { spec }) if spec == path => {
        eprintln!("`{path}` does not exist at `{rev}`");
    }
    Err(pi_vcs::Error::ObjectNotFound { .. }) => {
        eprintln!("revision unreachable — try `git fetch --unshallow`");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Resolving a revision spec that does not parse to an object (misspelled SHA, abbreviated SHA too short/ambiguous-pruned, `HEAD~50` beyond history in a shallow clone), or reading a blob/tree path that does not exist at the given commit (wrong file path, file not in that revision).

Common situations: Shallow or partial clones missing deep history (`git log` beyond the depth), history rewritten by rebase/filter-branch so old SHAs vanished, requesting a path that was renamed or added after the requested commit, or hash from another repo.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/91f39f79335cd9c0. Report an issue: GitHub.