{"record":{"id":"685aa0f2caaf614c","repo":"nikivdev/code","slug":"unable-to-parse-repository-path-from","errorCode":null,"errorMessage":"unable to parse repository path from: {}","messagePattern":"unable to parse repository path from: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/repos.rs","lineNumber":1691,"sourceCode":"    !trimmed.contains(\"://\") && !trimmed.contains('@')\n}\n\nfn parse_generic_repo(input: &str) -> Result<GenericRepoRef> {\n    let trimmed = input.trim();\n    if trimmed.is_empty() {\n        bail!(\"missing repository URL\");\n    }\n\n    if let Ok(url) = Url::parse(trimmed) {\n        let path = url\n            .path()\n            .trim_matches('/')\n            .split('/')\n            .filter(|p| !p.is_empty())\n            .map(|p| p.trim_end_matches(\".git\").to_string())\n            .collect::<Vec<_>>();\n        if path.is_empty() {\n            bail!(\"unable to parse repository path from: {}\", input);\n        }\n        return Ok(GenericRepoRef {\n            path,\n            clone_url: trimmed.to_string(),\n        });\n    }\n\n    if let Some(at) = trimmed.find('@') {\n        if let Some(colon) = trimmed[at + 1..].find(':') {\n            let rest = &trimmed[at + 1 + colon + 1..];\n            let path = rest\n                .trim_matches('/')\n                .split('/')\n                .filter(|p| !p.is_empty())\n                .map(|p| p.trim_end_matches(\".git\").to_string())\n                .collect::<Vec<_>>();\n            if path.is_empty() {\n                bail!(\"unable to parse repository from: {}\", input);","sourceCodeStart":1673,"sourceCodeEnd":1709,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/repos.rs#L1673-L1709","documentation":"When Url::parse succeeds, parse_generic_repo splits the URL path into non-empty segments (stripping a trailing .git) and requires at least one segment. A URL with an empty path — e.g. https://github.com or https://example.com/ — has no repository path, so the function bails with this message naming the original input.","triggerScenarios":"Passing a bare host URL like \"https://github.com\", \"https://gitlab.com/\", or \"https://host\" (optionally with query/fragment) to parse_generic_repo; the path component contains no '/'-separated segments.","commonSituations":"User pasted the site homepage instead of the repo URL; trailing-slash-only path after stripping; a config template with an unfilled host placeholder; redirects/short links that lost the path.","solutions":["Include the repository path in the URL, e.g. https://host/owner/repo.git","Verify the URL points at a repository page, not the host root","Normalize/validate that the URL path has at least one segment before calling"],"exampleFix":"// before\nlet r = parse_generic_repo(\"https://github.com\")?;\n// after\nlet r = parse_generic_repo(\"https://github.com/owner/repo.git\")?;","handlingStrategy":"validation","validationCode":"use url::Url;\nfn has_repo_path(input: &str) -> bool {\n    Url::parse(input.trim()).ok()\n        .map_or(false, |u| u.path().trim_matches('/').split('/').any(|p| !p.is_empty()))\n}","typeGuard":"fn is_full_repo_url(input: &str) -> bool {\n    input.contains(\"://\") && input.trim_end_matches(\"/\").rsplit('/').next().map_or(false, |s| !s.is_empty())\n}","tryCatchPattern":"let r = parse_generic_repo(input)\n    .map_err(|e| anyhow!(\"bad repo value {:?}: {e}\", input))?;","preventionTips":["Use full repository URLs including owner/repo, not host roots","Check pasted URLs point at a repo page, not the site home","Validate URL path depth before parsing","Strip query/fragment noise from user-supplied URLs"],"tags":["input-validation","url-parsing","git"],"backgroundTag":"invalid-repository-url","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}