nikivdev/code · error

jj {} failed: {}

Error message

jj {} failed: {}

What it means

Generic failure wrapper for fire-and-forget jj commands (via `jj_run_in`). When the spawned `jj <args>` process exits non-zero, the function combines the command name with the captured stderr (falling back to stdout when stderr is empty) and bails with this formatted message. It surfaces jj's own diagnostics verbatim to the caller.

Source

Thrown at src/commit.rs:8463

    }
    false
}

fn jj_run_in(repo_root: &Path, args: &[&str]) -> Result<()> {
    let output = Command::new(jj_bin())
        .current_dir(repo_root)
        .args(args)
        .output()
        .with_context(|| format!("failed to run jj {}", args.join(" ")))?;
    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        let stdout = String::from_utf8_lossy(&output.stdout);
        let msg = if stderr.trim().is_empty() {
            stdout.trim()
        } else {
            stderr.trim()
        };
        bail!("jj {} failed: {}", args.join(" "), msg);
    }
    Ok(())
}

fn jj_capture_in(repo_root: &Path, args: &[&str]) -> Result<String> {
    let output = Command::new(jj_bin())
        .current_dir(repo_root)
        .args(args)
        .output()
        .with_context(|| format!("failed to run jj {}", args.join(" ")))?;
    if !output.status.success() {
        let stderr = String::from_utf8_lossy(&output.stderr);
        let stdout = String::from_utf8_lossy(&output.stdout);
        let msg = if stderr.trim().is_empty() {
            stdout.trim()
        } else {
            stderr.trim()
        };

View on GitHub (pinned to a747e741ae)

Solutions

  1. Read the jj message appended after 'jj {} failed:' — it is jj's own diagnostic
  2. Re-run the exact jj command manually in the repo root to reproduce
  3. Check that the jj binary version supports the flags used
  4. Ensure the workspace is valid (`jj st` succeeds) before retrying

Example fix

// before
Error: jj describe failed: Error: working copy is stale
// after
$ jj workspace update-stale  # or `jj st` to auto-update
$ tool commit                 # retry the operation
Defensive patterns

Strategy: try-catch

Validate before calling

let out = Command::new("jj").args(["st"]).output()?;
if !out.status.success() {
    return Err(anyhow!("jj workspace not usable: {}",
        String::from_utf8_lossy(&out.stderr)));
}

Try / catch

if let Err(e) = result {
    let msg = e.to_string();
    if msg.contains("failed:") {
        eprintln!("jj command failed; rerun manually to debug: jj <subcommand>");
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Any call to the fire-and-forget jj helper where `output.status.success()` is false — e.g. `jj new`, `jj describe`, or `jj bookmark set` failing due to invalid arguments, unresolvable revisions, or workspace issues.

Common situations: Typo'd or unsupported jj subcommand/flag on older jj versions; referencing a revision that does not exist; jj workspace not initialized in the repo; authentication or git-backend errors surfaced through jj.

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/979e833b6be3691f. Report an issue: GitHub.