nikivdev/code · error

jj git fetch failed: {}

Error message

jj git fetch failed: {}

What it means

Thrown in src/sync.rs when the internal `jj git fetch` invocation fails. The tool collects per-remote fetch failures and, if any remain after the fetch attempt, bails with the joined error messages. This wraps lower-level jj/git fetch errors (network auth, missing remote, refspec problems).

Source

Thrown at src/sync.rs:3517

                failures.push(format!(
                    "origin alias {}: {}",
                    upstream_branch_for_fetch, err
                ));
            } else {
                fetched_any = true;
            }
        }

        if fetched_any {
            recorder.record("jj", "jj git import");
            let _ = jj_run_in(repo_root, &["--quiet", "git", "import"]);
            print_fetched_remote_commits(repo_root, &tracked_refs, recorder, cmd.compact);
            // Re-resolve after fetch/import so we can pick up newly discovered upstream refs.
            if home_branch_sync_target.is_none() {
                upstream_branch_opt = resolve_upstream_branch_in(repo_root, Some(&current_branch));
            }
        } else if !failures.is_empty() {
            bail!("jj git fetch failed: {}", failures.join(", "));
        }
    }

    let push_remote_url =
        git_capture_in(repo_root, &["remote", "get-url", &push_remote]).unwrap_or_default();
    let upstream_url =
        git_capture_in(repo_root, &["remote", "get-url", "upstream"]).unwrap_or_default();
    let is_read_only =
        has_upstream && normalize_git_url(&push_remote_url) == normalize_git_url(&upstream_url);

    let mut dest_ref: Option<String> = None;
    if let Some(target) = home_branch_sync_target.as_ref() {
        dest_ref = Some(format!(
            "{}@{}",
            target.public_default_branch, target.public_remote
        ));
    } else if has_upstream {
        if let Some(branch) = upstream_branch_opt {

View on GitHub (pinned to a747e741ae)

Solutions

  1. Read the joined message after the colon — it names the failing remote/reason; fix that specific issue (e.g., `ssh -T git@host` to test auth).
  2. Verify the remote exists: `git remote -v` / `jj git remote list`, and re-add if missing (`jj git remote add origin <url>`).
  3. Retry when network/VPN is up; fetch is safe to re-run.
  4. Refresh credentials: start ssh-agent with the key, or update HTTPS token in your credential helper.

Example fix

// before
jj git fetch origin
// error: authentication failed for 'https://gitlab.com/team/repo.git'

// after (refresh credentials then re-run sync)
git credential reject <<EOF
protocol=https
host=gitlab.com
EOF
f sync
Defensive patterns

Strategy: retry

Validate before calling

git ls-remote origin HEAD >/dev/null 2>&1 || { echo "origin unreachable or auth failed"; exit 1; }

Try / catch

match sync::run(&repo_root, &cmd) {
    Err(e) if e.to_string().starts_with("jj git fetch failed:") => {
        eprintln!("Fetch failed: {} — check auth/network, then retry", e);
        // retry with backoff
    }
    other => other,
}

Prevention

When it happens

Trigger: Executing the sync command when `jj git fetch` returns failures for one or more remotes — the `else if !failures.is_empty()` branch. Any non-empty `failures` list (e.g., SSH auth rejected, remote URL unreachable, unknown remote name) triggers it.

Common situations: SSH key not loaded in agent or wrong passphrase; remote renamed/removed; no network/VPN; jj repo not colocated with git so the git remote isn't registered with jj; credentials expired.

Related errors


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