{"record":{"id":"9f643b7fc3a84ffc","repo":"nikivdev/code","slug":"repos-root-is-immutable-use-or-or-set-1","errorCode":null,"errorMessage":"repos root is immutable; use {} or {} or set {}=1 to override","messagePattern":"repos root is immutable; use (.+?) or (.+?) or set (.+?)=1 to override","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/repos.rs","lineNumber":1773,"sourceCode":"    Ok(RepoRef {\n        owner: owner.to_string(),\n        repo: repo.to_string(),\n    })\n}\n\npub(crate) fn normalize_root(raw: &str) -> Result<PathBuf> {\n    let expanded = config::expand_path(raw);\n    let cwd = std::env::current_dir().context(\"failed to resolve current directory\")?;\n    let root = if expanded.is_absolute() {\n        expanded\n    } else {\n        cwd.join(expanded)\n    };\n\n    let default_repos_root = config::expand_path(DEFAULT_REPOS_ROOT);\n    let default_code_root = config::expand_path(DEFAULT_CODE_ROOT);\n    if root != default_repos_root && root != default_code_root && !repos_root_override_enabled() {\n        bail!(\n            \"repos root is immutable; use {} or {} or set {}=1 to override\",\n            default_repos_root.display(),\n            default_code_root.display(),\n            REPOS_ROOT_OVERRIDE_ENV\n        );\n    }\n\n    Ok(root)\n}\n\nfn repos_root_override_enabled() -> bool {\n    match std::env::var(REPOS_ROOT_OVERRIDE_ENV) {\n        Ok(value) => {\n            let trimmed = value.trim();\n            !trimmed.is_empty() && trimmed != \"0\"\n        }\n        Err(_) => false,\n    }","sourceCodeStart":1755,"sourceCodeEnd":1791,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/repos.rs#L1755-L1791","documentation":"The repos-root guard in src/repos.rs refuses to operate on a repository root other than the two built-in defaults (DEFAULT_REPOS_ROOT or DEFAULT_CODE_ROOT) unless an explicit override is enabled. This protects users from accidentally cloning, syncing, or mutating repos in an arbitrary directory that may not be managed by this tool.","triggerScenarios":"Calling a repos command with a custom root path argument that matches neither config::expand_path(DEFAULT_REPOS_ROOT) nor config::expand_path(DEFAULT_CODE_ROOT) while the REPOS_ROOT_OVERRIDE_ENV environment variable is unset.","commonSituations":"Developers passing --root or a positional path pointing at a scratch/personal directory; CI systems overriding the root without also setting the override env var; expansions of '~' differing from the configured default path.","solutions":["Use the default repos root or default code root instead of a custom path","Set the REPOS_ROOT_OVERRIDE_ENV environment variable to 1 to explicitly allow a non-default root","Verify the path is correctly expanded (config::expand_path) and matches one of the two allowed defaults"],"exampleFix":"// before\nrepos_cmd(root: PathBuf::from(\"/tmp/my-repos\"), ...)\n// after\nexport REPOS_ROOT_OVERRIDE=1  # or pass the default root\nrepos_cmd(root: config::expand_path(DEFAULT_REPOS_ROOT), ...)","handlingStrategy":"validation","validationCode":"fn is_allowed_repos_root(root: &Path) -> bool {\n    let d = config::expand_path(DEFAULT_REPOS_ROOT);\n    let c = config::expand_path(DEFAULT_CODE_ROOT);\n    root == d || root == c || std::env::var(REPOS_ROOT_OVERRIDE_ENV).as_deref() == Ok(\"1\")\n}\nif !is_allowed_repos_root(&root) { eprintln!(\"root not allowed\"); return; }","typeGuard":null,"tryCatchPattern":"match do_repos_op(&root) {\n    Err(e) if e.to_string().contains(\"repos root is immutable\") => eprintln!(\"pass the default root or set the override env var\"),\n    other => other?,\n}","preventionTips":["Always derive the root from config::expand_path(DEFAULT_*) instead of hardcoding paths","Set REPOS_ROOT_OVERRIDE_ENV=1 only in throwaway/dev environments","Document the allowed roots in your CI scripts"],"tags":["cli","config","validation"],"backgroundTag":"invalid-config-path","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}