nikivdev/code · error

Source is not a jj workspace. Run `jj git init --colocate` i

Error message

Source is not a jj workspace. Run `jj git init --colocate` in {} and retry.

What it means

prepare_source_workspace calls jj_root(source) to locate the jj repository root; if the source directory is not inside a jj workspace, jj_root fails and the tool bails with instructions to initialize one with `jj git init --colocate`.

Source

Thrown at src/ext.rs:244

    #[cfg(not(unix))]
    {
        let metadata =
            fs::metadata(target).with_context(|| format!("failed to read {}", target.display()))?;
        if metadata.is_dir() {
            copy_dir_all(target, dest)?;
        } else {
            fs::copy(target, dest)
                .with_context(|| format!("failed to copy {}", target.display()))?;
        }
        Ok(())
    }
}

fn prepare_source_workspace(source: &Path, project_root: &Path) -> Result<PathBuf> {
    let repo_root = match jj_root(source) {
        Ok(root) => root,
        Err(_) => {
            bail!(
                "Source is not a jj workspace. Run `jj git init --colocate` in {} and retry.",
                source.display()
            );
        }
    };

    let workspace = workspace_name_for_project(project_root)?;
    if workspace.is_empty() {
        return Ok(source.to_path_buf());
    }

    let status = git_capture_in(&repo_root, &["status", "--porcelain"]).unwrap_or_default();
    if !status.trim().is_empty() {
        println!("Source repo has uncommitted changes:");
        for line in status.lines().take(20) {
            println!("  {line}");
        }
        let continue_anyway = prompt_yes_no(

View on GitHub (pinned to a747e741ae)

Solutions

  1. Run `jj git init --colocate` inside the source directory, then retry the import.
  2. Point the import at the actual jj workspace root instead of a subfolder outside it.
  3. Confirm jj is installed and on PATH (`jj --version`), since a missing binary also makes jj_root fail.

Example fix

// before (shell)
import-external ~/repos/plain-git-repo
// after (shell)
cd ~/repos/plain-git-repo && jj git init --colocate
import-external ~/repos/plain-git-repo
Defensive patterns

Strategy: validation

Validate before calling

let ok = std::process::Command::new("jj")
    .args(["root"])
    .current_dir(source)
    .output()
    .map(|o| o.status.success())
    .unwrap_or(false);
if !ok {
    return Err(anyhow!("{} is not a jj workspace; run `jj git init --colocate` there", source));
}
import_external_path(source)?;

Type guard

fn is_jj_workspace(dir: &Path) -> bool {
    dir.join(".jj").exists() || dir.ancestors().any(|a| a.join(".jj").exists())
}

Try / catch

if let Err(e) = import_external_path(source) {
    if e.to_string().contains("not a jj workspace") {
        eprintln!("Initialize first: cd {source} && jj git init --colocate");
    } else { return Err(e.into()); }
}

Prevention

When it happens

Trigger: import_external_path given a directory that is a plain folder or a git-only repo (no .jj/), so `jj root` (via jj_capture_in) exits non-zero inside jj_root.

Common situations: Importing a freshly cloned git repo that was never colocated; importing an empty or non-VCS directory; jj not installed so the probe fails even in a valid workspace.

Related errors


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