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
- Verify the repo marker path shown in the message exists (ls <path>); recreate/re-clone the repo if deleted.
- Fix the workspace/config entry that references the stale repository path.
- 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
- Keep workspace config paths in sync when moving/cloning repos.
- Check repo existence before running multi-repo workflows.
- Avoid deleting repo directories referenced by active workspaces.
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
- Lin.app is not running
- {} is not inside a git repository
- derived shared repo root {} does not contain .git
- Refusing to remove non-Flow hook at {}.
- missing push remote for {}
AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01).
Data as JSON: /api/errors/f522f5202394b111.
Report an issue: GitHub.