{"record":{"id":"36932165b25bfec2","repo":"Hmbown/CodeWhale","slug":"pass-a-host-like-github-com-not-a-url-path","errorCode":null,"errorMessage":"Pass a host like `github.com`, not a URL path","messagePattern":"Pass a host like `github\\.com`, not a URL path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"crates/tui/src/commands/groups/utility/network.rs","lineNumber":277,"sourceCode":"    if !list\n        .iter()\n        .any(|existing| normalize_host_for_compare(existing) == host)\n    {\n        list.push(host.to_string());\n    }\n}\n\nfn remove_host(list: &mut Vec<String>, host: &str) {\n    list.retain(|existing| normalize_host_for_compare(existing) != host);\n}\n\nfn normalize_host_arg(input: &str) -> anyhow::Result<String> {\n    let trimmed = input.trim();\n    let host = if trimmed.starts_with(\"http://\") || trimmed.starts_with(\"https://\") {\n        host_from_url(trimmed).context(\"URL must include a host\")?\n    } else {\n        if trimmed.contains(\"://\") || trimmed.contains('/') {\n            bail!(\"Pass a host like `github.com`, not a URL path\");\n        }\n        trimmed.to_string()\n    };\n\n    let normalized = normalize_host_for_compare(&host);\n    if normalized.is_empty() {\n        bail!(\"host cannot be empty\");\n    }\n    Ok(normalized)\n}\n\n/// Extract the host portion of a URL, lowercased (leaf `reqwest::Url` parse;\n/// no TUI helper dependency).\nfn host_from_url(url: &str) -> Option<String> {\n    let parsed = reqwest::Url::parse(url.trim()).ok()?;\n    parsed.host_str().map(str::to_ascii_lowercase)\n}\n","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/commands/groups/utility/network.rs#L259-L295","documentation":"normalize_host_arg rejects inputs that look like a URL path rather than a bare host. If the input contains `://` (not a plain http/https prefix that can be salvaged) or a `/`, it bails telling the user to pass a hostname like `github.com`. The rules operate on hostnames, not full URLs or paths.","triggerScenarios":"`/network allow ftp://example.com`, `/network allow github.com/org/repo`, or any argument containing a `/` without an http(s) scheme prefix.","commonSituations":"Pasting a full repository URL or an API endpoint path instead of the hostname; using non-http schemes like ftp:// or ws:// which are not auto-parsed.","solutions":["Pass only the hostname: `github.com`, not `https://github.com/org/repo`","If you have an http(s) URL, the command extracts its host automatically; strip other schemes manually","Use a wildcard host (e.g. `*.example.com`) instead of URL paths for subpath rules"],"exampleFix":"// before\n/network allow https://github.com/org/repo\n// after\n/network allow github.com","handlingStrategy":"validation","validationCode":"function isBareHost(s) {\n  const t = s.trim();\n  if (t.includes('/') || /\\w+:\\/\\//.test(t)) return false;\n  return t.length > 0;\n}\nif (!isBareHost(arg)) throw new Error('Pass a host like `github.com`');","typeGuard":"const isBareHost = (s: string): boolean => {\n  const t = s.trim();\n  return t.length > 0 && !t.includes('/') && !t.includes('://');\n};","tryCatchPattern":"try { run('/network allow ' + arg); } catch (e) { if (String(e).includes('URL path')) arg = new URL(arg).host; }","preventionTips":["Pass hostnames only, not URLs or paths","http(s) URLs are auto-parsed to their host; other schemes are not","Extract the host yourself before invoking with unusual input"],"tags":["cli","invalid-argument","url"],"backgroundTag":"invalid-url-format","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}