ducaale/xh · error

Value should be formatted as

Error message

Value should be formatted as <HOST>:<ADDRESS> (not <HOST>:<PORT>:<ADDRESS>)

What it means

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.

Solutions

  1. Drop the port segment: pass only <HOST>:<ADDRESS>, e.g. example.com:1.2.3.4
  2. If you meant an IPv6 address, bracket it so colons stay inside one segment: '[::1]:address' — or use the tool's documented IPv6 syntax
  3. 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

Example fix

// before
xh --resolve example.com:443:93.184.216.34 GET https://example.com
// after
xh --resolve example.com:93.184.216.34 GET https://example.com
Defensive patterns

Strategy: validation

Validate before calling

fn validate_resolve_arg(arg: &str) -> Result<(), String> {
    let colons = arg.matches(':').count();
    if colons != 1 {
        return Err(format!("expected exactly one ':' (got {}); use <HOST>:<ADDRESS>", colons));
    }
    Ok(())
}

Try / catch

match ResolveArg::from_str(&arg) {
    Ok(r) => r,
    Err(e) if e.to_string().contains("<HOST>:<ADDRESS>") =>
        eprintln!("Drop the port segment; put the port in the request URL instead"),
    Err(e) => eprintln!("--resolve rejected: {e}"),
}

Prevention

When it happens

Trigger: 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.

Common situations: Copying curl's --resolve HOST:PORT:ADDRESS syntax into this tool, or trying to pin an IPv6 host without [brackets].

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of ducaale/xh@2404aceecc (2026-09-13). Data as JSON: /api/errors/958ea6fc304f1927. Report an issue: GitHub.

Appendix: source

Thrown at src/cli.rs:1266

            )),
        }
    }
}

#[derive(Debug, Clone)]
pub struct Resolve {
    pub domain: String,
    pub addr: IpAddr,
}

impl FromStr for Resolve {
    type Err = anyhow::Error;

    fn from_str(s: &str) -> anyhow::Result<Self> {
        if s.chars().filter(|&c| c == ':').count() == 2 {
            // More than two colons could mean an IPv6 address.
            // Exactly two colons probably means the user added a port, curl-style.
            return Err(anyhow!(
                "Value should be formatted as <HOST>:<ADDRESS> (not <HOST>:<PORT>:<ADDRESS>)"
            ));
        }

        let (domain, raw_addr) = s
            .split_once(':')
            .context("Value should be formatted as <HOST>:<ADDRESS>")?;

        let addr = if raw_addr.starts_with('[') && raw_addr.ends_with(']') {
            // Support IPv6 addresses enclosed in square brackets e.g. [::1]
            Ipv6Addr::from_str(&raw_addr[1..raw_addr.len() - 1]).map(IpAddr::V6)
        } else {
            raw_addr.parse()
        }
        .with_context(|| format!("Invalid address '{raw_addr}'"))?;

        Ok(Resolve {
            domain: domain.to_string(),

View on GitHub (pinned to 2404aceecc)