{"record":{"id":"ad67395e5a33f3b3","repo":"can1357/oh-my-pi","slug":"positional-paths-cannot-be-combined-with-search","errorCode":null,"errorMessage":"positional paths cannot be combined with --search-path","messagePattern":"positional paths cannot be combined with --search-path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/pi-builtins/src/fd.rs","lineNumber":1145,"sourceCode":"fn matches_owner_filters(filters: &[OwnerMatcher], _metadata: Option<&Metadata>) -> bool {\n\tfilters.is_empty()\n}\n\n#[cfg(unix)]\nconst fn owner_side_matches(side: OwnerSide, actual: u32) -> bool {\n\tmatch side {\n\t\tOwnerSide::Include(expected) => actual == expected,\n\t\tOwnerSide::Exclude(expected) => actual != expected,\n\t}\n}\n\nfn resolve_search_paths(\n\tcli: &FdCli,\n\tbase_dir: &Path,\n\thost: &Host,\n) -> io::Result<Vec<SearchPath>> {\n\tif !cli.search_paths.is_empty() && !cli.paths.is_empty() {\n\t\treturn Err(io::Error::new(\n\t\t\tio::ErrorKind::InvalidInput,\n\t\t\t\"positional paths cannot be combined with --search-path\",\n\t\t));\n\t}\n\tlet raw_paths = if !cli.search_paths.is_empty() {\n\t\tcli.search_paths.clone()\n\t} else if !cli.paths.is_empty() {\n\t\tcli.paths.clone()\n\t} else {\n\t\tvec![PathBuf::from(\".\")]\n\t};\n\tOk(raw_paths\n\t\t.into_iter()\n\t\t.map(|original| {\n\t\t\tlet resolved = if original.is_absolute() {\n\t\t\t\thost.resolve(&original)\n\t\t\t} else {\n\t\t\t\thost.resolve(base_dir.join(&original))","sourceCodeStart":1127,"sourceCodeEnd":1163,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/crates/pi-builtins/src/fd.rs#L1127-L1163","documentation":"fd's resolve_search_paths treats --search-path entries and bare positional paths as two mutually exclusive ways to specify where to search. Supplying both is ambiguous, so it returns InvalidInput immediately before doing any work.","triggerScenarios":"`fd pattern dir1 --search-path dir2`, or scripts appending a positional path while a wrapper always injects --search-path.","commonSituations":"Wrapper functions/aliases that hardcode --search-path while the user also passes a path; copy-pasted commands merging two search-root styles.","solutions":["Remove the positional paths and keep everything in --search-path (it accepts multiple values)","Or drop --search-path and list positional roots instead — positional paths also support multiple values","In wrappers, pass roots through one parameter only and document the convention"],"exampleFix":"// before\nfd src --search-path tests\n// after\nfd --search-path src --search-path tests","handlingStrategy":"validation","validationCode":"function validateFdRoots(args) { const hasPos = args.filter(a => !a.startsWith(\"-\")).length > 0; const hasSp = args.some(a => a === \"--search-path\" || a.startsWith(\"--search-path=\")); if (hasPos && hasSp) throw new Error(\"fd: use either positional paths or --search-path, not both\"); }","typeGuard":"fn search_paths_conflict(cli: &FdCli) -> bool { !cli.search_paths.is_empty() && !cli.paths.is_empty() }","tryCatchPattern":"if (!cli.search_paths.is_empty() && !cli.paths.is_empty()) { cli.paths = []; /* or merge into search_paths */ }","preventionTips":["Standardize on one root-specification style across scripts and wrappers","When wrapping fd, accept roots via a single parameter and forward to exactly one flag","Document in team tooling that --search-path supersedes positional paths"],"tags":["cli","argument-conflict","fd","rust"],"backgroundTag":"conflicting-cli-arguments","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}