{"record":{"id":"f69f8bd49561b255","repo":"nikivdev/code","slug":"jj-is-required-but-not-available-on-path","errorCode":null,"errorMessage":"jj is required but not available on PATH","messagePattern":"jj is required but not available on PATH","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/vcs.rs","lineNumber":14,"sourceCode":"use std::path::{Path, PathBuf};\nuse std::process::Command;\n\nuse anyhow::{Context, Result, bail};\n\npub fn ensure_jj_installed() -> Result<()> {\n    let status = Command::new(\"jj\")\n        .arg(\"--version\")\n        .stdout(std::process::Stdio::null())\n        .stderr(std::process::Stdio::null())\n        .status()\n        .context(\"failed to run jj --version\")?;\n    if !status.success() {\n        bail!(\"jj is required but not available on PATH\");\n    }\n    Ok(())\n}\n\npub fn ensure_jj_repo() -> Result<PathBuf> {\n    let cwd = std::env::current_dir().context(\"failed to read current directory\")?;\n    ensure_jj_repo_in(&cwd)\n}\n\npub fn ensure_jj_repo_in(path: &Path) -> Result<PathBuf> {\n    ensure_jj_installed()?;\n    if let Ok(root) = try_jj_root(path) {\n        return Ok(root);\n    }\n\n    let git_dir = path.join(\".git\");\n    if git_dir.exists() {\n        let status = Command::new(\"jj\")","sourceCodeStart":1,"sourceCodeEnd":32,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/vcs.rs#L1-L32","documentation":"ensure_jj_installed verifies that the jj (Jujutsu) VCS binary is usable by running `jj --version`. If the command exits with a non-zero status (typically because jj is not installed or not on PATH), it bails with this error. It is thrown before any jj repository operations are attempted so callers fail fast with a clear message.","triggerScenarios":"Calling ensure_jj_installed() (directly or via ensure_jj_repo_in -> ensure_jj_repo) when the `jj` executable is missing from PATH, is not executable, or `jj --version` exits non-zero.","commonSituations":"Fresh machines or CI containers where Jujutsu was never installed; jj installed via a tool manager (cargo/homebrew) whose bin dir is not on PATH for the current shell or service user; a broken/partial jj installation where the binary exists but fails to run; PATH differences between an interactive shell and a systemd/cron/IDE-spawned process.","solutions":["Install Jujutsu (e.g. `cargo install jj-cli`, `brew install jj`, or your distro package) and confirm `jj --version` works in a terminal.","Fix PATH for the environment running this code: add jj's install bin dir to PATH in the shell profile, service unit, or CI environment.","Verify the binary is executable (`chmod +x $(which jj)`) or reinstall it if `jj --version` fails despite being found.","If jj is installed in a known non-PATH location, prepend that directory to PATH programmatically before calling the library."],"exampleFix":"// before (CI job without jj)\n- run: ./mytool sync   # panics: jj is required but not available on PATH\n// after\n- run: cargo install jj-cli\n- run: jj --version\n- run: ./mytool sync","handlingStrategy":"validation","validationCode":"use std::process::Command;\nfn jj_available() -> bool {\n    Command::new(\"jj\")\n        .arg(\"--version\")\n        .stdout(std::process::Stdio::null())\n        .stderr(std::process::Stdio::null())\n        .status()\n        .map(|s| s.success())\n        .unwrap_or(false)\n}\nif !jj_available() {\n    eprintln!(\"Install jj (cargo install jj-cli) and ensure it is on PATH\");\n    std::process::exit(1);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check `which jj` (or `jj --version`) in setup scripts/CI before invoking the library","Install jj as an explicit dependency step in Dockerfiles and CI pipelines","For services/cron, set PATH explicitly in the unit or crontab since they don't inherit your shell PATH","Keep jj updated so `jj --version` never fails due to a broken install"],"tags":["vcs","jj","missing-binary","path"],"backgroundTag":"required-binary-not-on-path","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}