can1357/oh-my-pi · error · Error
cli_message(command, exit_code, stdout, stderr)
Error message
cli_message(command, exit_code, stdout, stderr)
What it means
Error::Cli is raised when a CLI-backed operation (push/fetch/clone, reftable fallback) exits non-zero. It carries the rendered command line, exit code, and captured stdout/stderr (possibly truncated) so user-facing error surfaces can show exactly what git/jj printed.
Source
Thrown at crates/pi-vcs/src/error.rs:64
/// A merge-style operation (cherry-pick, stash pop, 3-way apply) hit
/// conflicting changes.
#[error("merge conflict in {} file(s)", paths.len())]
Conflict {
/// Worktree-relative paths left in a conflicted state.
paths: Vec<String>,
},
/// A patch did not apply (context mismatch, missing file, malformed input).
#[error("patch does not apply: {message}")]
PatchFailed {
/// Human-readable reason, including the offending path when known.
message: String,
},
/// A CLI-backed operation (push/fetch/clone, reftable fallback) exited
/// non-zero. Carries the captured streams for user-facing error surfaces.
#[error("{}", crate::error::cli_message(command, *exit_code, stdout, stderr))]
Cli {
/// Rendered command line (`git push --no-follow-tags …`).
command: String,
/// Process exit code.
exit_code: i32,
/// Captured stdout (may be truncated).
stdout: String,
/// Captured stderr (may be truncated).
stderr: String,
},
/// A CLI-backed operation exceeded its deadline and was killed.
#[error("timed out: {command}")]
CliTimeout {
/// Rendered command line.
command: String,
},
View on GitHub (pinned to 9690622007)
Solutions
- Read `stderr` in the error — git's own message usually names the exact problem (auth, rejected non-fast-forward, unknown option).
- For push rejections: `git pull --rebase` (fetch and integrate remote state), then push again.
- For auth failures: refresh credentials (`gh auth login`, ssh-add, credential manager) and retry.
- For unknown-option failures, upgrade the installed git/jj binary to a version supporting the flags used.
Example fix
// before
repo.push("origin", "main")?; // opaque failure
// after
if let Err(Error::Cli { command, exit_code, stderr, .. }) = repo.push("origin", "main") {
eprintln!("{command} exited {exit_code}:\n{stderr}");
if stderr.contains("non-fast-forward") { repo.pull_rebase("origin", "main")?; repo.push("origin", "main")?; }
} Defensive patterns
Strategy: try-catch
Validate before calling
fn remote_reachable(url: &str) -> bool {
std::process::Command::new("git").args(["ls-remote", "--exit-code", url, "HEAD"])
.status().map(|s| s.success()).unwrap_or(false)
}
if !remote_reachable(&remote_url) { eprintln!("cannot reach {remote_url} — check network/auth"); return Ok(()); } Type guard
fn is_cli_error(err: &pi_vcs::Error) -> Option<(i32, &str)> {
match err {
pi_vcs::Error::Cli { exit_code, stderr, .. } => Some((*exit_code, stderr)),
_ => None,
}
} Try / catch
match repo.push("origin", branch) {
Err(pi_vcs::Error::Cli { exit_code, stderr, .. }) => {
if stderr.contains("non-fast-forward") {
repo.pull_rebase("origin", branch)?;
repo.push("origin", branch)?;
} else {
anyhow::bail!("push failed (exit {exit_code}):\n{stderr}");
}
}
other => other?,
} Prevention
- Keep credentials fresh (ssh-agent loaded, credential helper configured) before automated push/fetch.
- Pull/rebase before pushing to reduce non-fast-forward rejections.
- Pin a recent git/jj version in CI so library-passed flags are always supported.
- Always surface stderr from this variant in user-facing error messages — git's text names the cause.
When it happens
Trigger: Any CLI-spawned git/jj command failing: `git push` rejected (non-fast-forward, no upstream, auth failure), `git fetch` network/auth errors, `git clone` of a nonexistent URL, or the reftable fallback path failing against an old git binary.
Common situations: Expired/missing credentials (HTTPS token revoked, SSH agent not loaded), branch protected on the remote, remote behind local history (need pull/rebase), offline/VPN-down, or git too old to support a flag the library passes.
Related errors
- timed out: {command}
- not a repository: {path}
- reference not found: {name}
- object not found: {spec}
- cherry-pick of {sha} is empty
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/06e7567734bf58f0.
Report an issue: GitHub.