{"record":{"id":"958ea6fc304f1927","repo":"ducaale/xh","slug":"value-should-be-formatted-as-host-address-not-host-port","errorCode":null,"errorMessage":"Value should be formatted as <HOST>:<ADDRESS> (not <HOST>:<PORT>:<ADDRESS>)","messagePattern":"Value should be formatted as <HOST>:<ADDRESS> \\(not <HOST>:<PORT>:<ADDRESS>\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/cli.rs","lineNumber":1266,"sourceCode":"            )),\n        }\n    }\n}\n\n#[derive(Debug, Clone)]\npub struct Resolve {\n    pub domain: String,\n    pub addr: IpAddr,\n}\n\nimpl FromStr for Resolve {\n    type Err = anyhow::Error;\n\n    fn from_str(s: &str) -> anyhow::Result<Self> {\n        if s.chars().filter(|&c| c == ':').count() == 2 {\n            // More than two colons could mean an IPv6 address.\n            // Exactly two colons probably means the user added a port, curl-style.\n            return Err(anyhow!(\n                \"Value should be formatted as <HOST>:<ADDRESS> (not <HOST>:<PORT>:<ADDRESS>)\"\n            ));\n        }\n\n        let (domain, raw_addr) = s\n            .split_once(':')\n            .context(\"Value should be formatted as <HOST>:<ADDRESS>\")?;\n\n        let addr = if raw_addr.starts_with('[') && raw_addr.ends_with(']') {\n            // Support IPv6 addresses enclosed in square brackets e.g. [::1]\n            Ipv6Addr::from_str(&raw_addr[1..raw_addr.len() - 1]).map(IpAddr::V6)\n        } else {\n            raw_addr.parse()\n        }\n        .with_context(|| format!(\"Invalid address '{raw_addr}'\"))?;\n\n        Ok(Resolve {\n            domain: domain.to_string(),","sourceCodeStart":1248,"sourceCodeEnd":1284,"githubUrl":"https://github.com/ducaale/xh/blob/2404aceecc08b0b2d100fedc96f57745cd5904dc/src/cli.rs#L1248-L1284","documentation":"FromStr for a --resolve-style host/address argument rejects values containing exactly two colons. Since the format is <HOST>:<ADDRESS>, two colons usually mean the user appended a curl-style port (<HOST>:<PORT>:<ADDRESS>) or passed an unbracketed IPv6 address, both ambiguous, so the parser fails fast.","triggerScenarios":"Passing --resolve example.com:443:1.2.3.4 (curl-style with port) or --resolve example.com:8080:1.2.3.4; also unbracketed IPv6 in the host part.","commonSituations":"Copying curl's --resolve HOST:PORT:ADDRESS syntax into this tool, or trying to pin an IPv6 host without [brackets].","solutions":["Drop the port segment: pass only <HOST>:<ADDRESS>, e.g. example.com:1.2.3.4","If you meant an IPv6 address, bracket it so colons stay inside one segment: '[::1]:address' — or use the tool's documented IPv6 syntax","Combine with the port flag/option of the tool (e.g. put the port in the request URL) instead of baking it into the resolve value"],"exampleFix":"// before\nxh --resolve example.com:443:93.184.216.34 GET https://example.com\n// after\nxh --resolve example.com:93.184.216.34 GET https://example.com","handlingStrategy":"validation","validationCode":"fn validate_resolve_arg(arg: &str) -> Result<(), String> {\n    let colons = arg.matches(':').count();\n    if colons != 1 {\n        return Err(format!(\"expected exactly one ':' (got {}); use <HOST>:<ADDRESS>\", colons));\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"match ResolveArg::from_str(&arg) {\n    Ok(r) => r,\n    Err(e) if e.to_string().contains(\"<HOST>:<ADDRESS>\") =>\n        eprintln!(\"Drop the port segment; put the port in the request URL instead\"),\n    Err(e) => eprintln!(\"--resolve rejected: {e}\"),\n}","preventionTips":["Don't copy curl's HOST:PORT:ADDRESS syntax","Put the port in the request URL, not the resolve value","Bracket IPv6 literals if the host can be IPv6"],"tags":["cli","dns","resolve","argument-format","rust"],"backgroundTag":"invalid-argument-format","analyzedSha":"2404aceecc08b0b2d100fedc96f57745cd5904dc","analyzedAt":"2026-09-13T19:13:33.814Z","contentChangedAt":"2026-09-13T19:13:33.814Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}