nikivdev/code · error

jj git export retry loop should always return

Error message

jj git export retry loop should always return

What it means

This error is thrown by a repository-marker resolution routine in src/workflow.rs (near line 784). Given a repo marker path (e.g. a .git or .jj marker), it tries git/jj resolution branches; if none applies and the marker file simply does not exist on disk, it bails with "expected <marker path> to exist". It is a precondition assertion that the marker file representing the repo was present.

Source

Thrown at src/sync.rs:4653

            std::thread::sleep(delay);
            continue;
        }

        jj_print_output(&output);
        let failure = jj_failure_message(&args, &output);
        if is_git_index_lock_error(&failure_text) {
            let retries = JJ_GIT_EXPORT_LOCK_RETRY_DELAYS_MS.len();
            bail!(
                "{}. Git index stayed locked after {} retr{}; close competing git/jj processes or remove stale .git/index.lock, then retry.",
                failure,
                retries,
                if retries == 1 { "y" } else { "ies" }
            );
        }
        bail!("{}", failure);
    }

    unreachable!("jj git export retry loop should always return");
}

fn jj_run_in(repo_root: &Path, args: &[&str]) -> Result<()> {
    let output = jj_run_output_in(repo_root, args)?;
    jj_print_output(&output);
    if !output.status.success() {
        bail!("{}", jj_failure_message(args, &output));
    }
    Ok(())
}

fn jj_preferred_binary() -> std::path::PathBuf {
    if let Ok(path) = std::env::var("FLOW_JJ_BIN") {
        let candidate = PathBuf::from(path);
        if candidate.exists() {
            return candidate;
        }
    }

View on GitHub (pinned to a747e741ae)

Solutions

  1. Verify the repo marker path shown in the message exists (ls <path>); recreate/re-clone the repo if deleted.
  2. Fix the workspace/config entry that references the stale repository path.
  3. Run the workflow from the correct repo root so the marker resolves.

Example fix

// before (stale path in workspace config)
repo_marker = /home/user/work/old-repo/.git
// after
+ git clone git@host:work/old-repo.git /home/user/work/old-repo
+ # or update config to the new path /home/user/work/new-repo/.git
Defensive patterns

Strategy: validation

Validate before calling

if !std::path::Path::new(&repo_marker).exists() {
    return Err(anyhow!("repo marker {} missing; fix workspace config", repo_marker.display()));
}

Type guard

fn repo_marker_exists(p: &std::path::Path) -> bool { p.exists() }

Try / catch

match resolve_repo_marker(marker) {
    Err(e) if e.to_string().contains("expected") && e.to_string().contains("to exist") => {
        eprintln!("re-clone or fix the workspace path: {}", marker.display());
    }
    r => r?,
}

Prevention

When it happens

Trigger: Calling the repo-resolution helper with a repo_marker path whose file/directory does not exist on disk, and the path is not under a .jj repo (so the jj parent-resolution branch is skipped).

Common situations: A workspace entry pointing at a moved/deleted repo; config referencing a repo path that was never cloned; a stale cache entry after the repository directory was removed; running from a subpath after the repo was relocated.

Related errors


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