{"record":{"id":"ff6e1f9c1caaf099","repo":"xai-org/grok-build","slug":"invalid-worktree-id","errorCode":null,"errorMessage":"invalid worktree id {:?}","messagePattern":"invalid worktree id (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-fast-worktree/src/nfs/mod.rs","lineNumber":111,"sourceCode":"    #[cfg(target_os = \"linux\")]\n    {\n        if !grove_fuse_ready() {\n            tracing::info!(\"grove-fuse skipped: /dev/fuse or fusermount missing\");\n            return Ok(None);\n        }\n        let has_delegate = plan.btrfs_delegate.is_some();\n        if !has_delegate\n            && matches!(\n                crate::mount_info::current_mount_ns_status(),\n                crate::mount_info::MountNsStatus::Private\n            )\n        {\n            tracing::info!(\"grove-fuse skipped: private mount namespace\");\n            return Ok(None);\n        }\n    }\n    if !confined::is_safe_worktree_id(&plan.worktree_id) {\n        anyhow::bail!(\"invalid worktree id {:?}\", plan.worktree_id);\n    }\n    let linked = source_is_linked_local_view(opts, &plan.source);\n    if dest_is_projected_mount(&plan.source) {\n        if !linked {\n            tracing::info!(\n                source = %plan.source.display(),\n                \"nfs worktree skipped: source is itself an NFS mount\"\n            );\n            return Ok(None);\n        }\n        if matches!(plan.working_tree, WorkingTreeMode::PreserveWorkingTree) {\n            tracing::info!(\n                source = %plan.source.display(),\n                \"nfs worktree skipped: preserve on a linked local-codebase view\"\n            );\n            return Ok(None);\n        }\n    } else if !dest_is_known_unmounted(&plan.source) && !dest_is_mountpoint(&plan.source) {","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-fast-worktree/src/nfs/mod.rs#L93-L129","documentation":"try_grove_worktree validates the planned worktree id with confined::is_safe_worktree_id before contacting the daemon. A malformed or unsafe id (wrong charset/format) is rejected up front with 'invalid worktree id' so it never reaches the daemon.","triggerScenarios":"Calling try_grove_worktree with a plan whose worktree_id contains path separators, '..', non-ASCII/unsafe characters, or is otherwise not passing is_safe_worktree_id; callers include the storage-full mapping path and the invalid_worktree_id_never_contacts_daemon test.","commonSituations":"Deriving worktree ids from user/branch names without sanitizing (slashes in branch names); ids built by concatenating paths; older versions of the tool writing ids that the stricter validator now rejects.","solutions":["Sanitize the id before planning: replace '/', '\\\\', '..' and unsafe chars (e.g. use a slug/hash of the source path)","Use a library-provided id generator / the confined module helpers to mint valid ids","Check the plan construction to ensure worktree_id is the canonical id, not a path"],"exampleFix":"// before\nlet id = format!(\"{}\", branch_name); // \"feature/foo\"\n// after\nlet id: String = branch_name.chars().map(|c| if c.is_ascii_alphanumeric() || c=='-' || c=='_' { c } else { '_' }).collect();\nif !confined::is_safe_worktree_id(&id) { bail!(\"cannot derive safe worktree id from {:?}\", branch_name); }","handlingStrategy":"validation","validationCode":"fn safe_id(id: &str) -> bool {\n    !id.is_empty()\n        && id.len() <= 64\n        && id.chars().all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')\n}\nif !safe_id(&plan.worktree_id) { /* fix id before calling */ }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Sanitize branch/user input into ids (replace separators and dots)","Use the library's confined::is_safe_worktree_id before planning","Never derive worktree_id from a filesystem path"],"tags":["validation","worktree-id","nfs","input-validation"],"backgroundTag":"invalid-worktree-id","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}