{"record":{"id":"949622072925f5e1","repo":"nikivdev/code","slug":"has-an-empty-jj-repo-pointer","errorCode":null,"errorMessage":"{} has an empty .jj/repo pointer","messagePattern":"(.+?) has an empty \\.jj/repo pointer","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/pr_preview.rs","lineNumber":1400,"sourceCode":"fn find_jj_workspace_root(start: &Path) -> Option<PathBuf> {\n    let current = if start.is_dir() {\n        start.to_path_buf()\n    } else {\n        start.parent()?.to_path_buf()\n    };\n    current\n        .ancestors()\n        .find(|candidate| candidate.join(\".jj\").join(\"repo\").is_file())\n        .map(Path::to_path_buf)\n}\n\nfn resolve_repo_root_from_jj_workspace(workspace_root: &Path) -> Result<PathBuf> {\n    let pointer_path = workspace_root.join(\".jj\").join(\"repo\");\n    let pointer = fs::read_to_string(&pointer_path)\n        .with_context(|| format!(\"failed to read {}\", pointer_path.display()))?;\n    let pointer = pointer.trim();\n    if pointer.is_empty() {\n        bail!(\"{} has an empty .jj/repo pointer\", workspace_root.display());\n    }\n    let jj_repo_dir = if Path::new(pointer).is_absolute() {\n        PathBuf::from(pointer)\n    } else {\n        workspace_root.join(\".jj\").join(pointer)\n    }\n    .canonicalize()\n    .with_context(|| {\n        format!(\n            \"failed to resolve JJ repo pointer for {}\",\n            workspace_root.display()\n        )\n    })?;\n    let repo_root = jj_repo_dir\n        .parent()\n        .and_then(Path::parent)\n        .map(Path::to_path_buf)\n        .ok_or_else(|| {","sourceCodeStart":1382,"sourceCodeEnd":1418,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/pr_preview.rs#L1382-L1418","documentation":"For jj (Jujutsu) workspaces, the repo root is resolved via the `.jj/repo` pointer file, which holds the path to the jj repo store (absolute, or relative to `.jj/`). This error fires when that file exists but is empty after trimming, so the repo directory cannot be located.","triggerScenarios":"Running `f pr preview` in a jj workspace where `.jj/repo` exists but contains zero bytes or only whitespace.","commonSituations":"Interrupted `jj workspace add` / clone that left an empty pointer; manually created .jj scaffolding; filesystem truncation or a bad sync tool that emptied the file.","solutions":["Re-create the workspace with jj (`jj workspace add` or re-clone) so the pointer is regenerated","Inspect .jj/repo and write the correct repo-store path if you know it","Fall back to running against the git side if the workspace is colocated"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let p = workspace_root.join(\".jj\").join(\"repo\");\nlet content = std::fs::read_to_string(&p)?;\nif content.trim().is_empty() {\n    anyhow::bail!(\"{} is empty; recreate the jj workspace\", p.display());\n}","typeGuard":"fn has_valid_jj_pointer(root: &Path) -> bool {\n    std::fs::read_to_string(root.join(\".jj\").join(\"repo\"))\n        .map(|s| !s.trim().is_empty())\n        .unwrap_or(false)\n}","tryCatchPattern":"if let Err(e) = run_pr_preview(cmd) {\n    if e.to_string().contains(\"empty .jj/repo pointer\") {\n        eprintln!(\"Recreate the jj workspace before previewing\");\n    }\n}","preventionTips":["Recreate the workspace if .jj/repo is empty rather than hand-editing","Avoid tools that truncate files during sync","Check jj workspace health after interrupted clones"],"tags":["jj","jujutsu","pr","filesystem","corrupt-state"],"backgroundTag":"corrupt-vcs-metadata","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}