zeroclaw-labs/zeroclaw · error
IPv6 hosts are not supported in browser_open
Error message
IPv6 hosts are not supported in browser_open
What it means
extract_host rejects authorities beginning with '[', which is the RFC 3986 marker for an IPv6 literal such as [2001:db8::1] or [::1] (browser_open.rs:308-310). The colon-based host parser downstream cannot handle bracketed v6 addresses, so browser_open explicitly refuses them instead of mis-parsing. It is a capability limit, not a transient fault.
Source
Thrown at crates/zeroclaw-tools/src/browser_open.rs:309
WARN,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Reject)
.with_outcome(::zeroclaw_log::EventOutcome::Failure)
.with_attrs(::serde_json::json!({"url": url})),
"browser_open: invalid URL"
);
anyhow::Error::msg("Invalid URL")
})?;
if authority.is_empty() {
anyhow::bail!("URL must include a host");
}
if authority.contains('@') {
anyhow::bail!("URL userinfo is not allowed");
}
if authority.starts_with('[') {
anyhow::bail!("IPv6 hosts are not supported in browser_open");
}
let host = authority
.split(':')
.next()
.unwrap_or_default()
.trim()
.trim_end_matches('.')
.to_lowercase();
if host.is_empty() {
anyhow::bail!("URL must include a valid host");
}
Ok(host)
}
#[cfg(test)]View on GitHub (pinned to 88bb9c8533)
Solutions
- Use a hostname instead of the literal: map a DNS name or /etc/hosts entry (e.g. 'service.local') to the IPv6 address and open 'http://service.local:8080/health'.
- Use the IPv4 form of the address if the service also listens on v4; note that private/local v4 hosts additionally require a browser.allowed_private_hosts entry.
- Add the chosen hostname to [browser].allowed_domains in config.toml so the allowlist check passes.
Example fix
// before
{"url": "http://[::1]:8080/health"}
// after: /etc/hosts maps service.local -> ::1, config allowlists it
{"url": "http://service.local:8080/health"}
# config.toml
[browser]
allowed_domains = ["service.local"] Defensive patterns
Strategy: validation
Validate before calling
fn url_host_is_not_ipv6_literal(url: &str) -> bool {
let Some(rest) = url
.strip_prefix("https://")
.or_else(|| url.strip_prefix("http://"))
else {
return false;
};
let authority = rest.split(['/', '?', '#']).next().unwrap_or("");
!authority.starts_with('[')
} Prevention
- Use DNS names or /etc/hosts entries for IPv6 services instead of bracketed literals.
- Add the hostname you choose to [browser].allowed_domains (or allowed_private_hosts for local ones).
- Reject URLs whose authority starts with '[' before calling browser_open to get a clearer upstream error.
When it happens
Trigger: Calling browser_open with 'http://[::1]:8080/health', 'https://[2001:db8::25de::ad24]/page', or any URL whose host is written as a bracketed IPv6 literal. Typical when targeting local or LAN services addressed by raw v6 address.
Common situations: Local development against services bound to ::1, dual-stack networks where DNS returns v6 and someone copied the literal, and monitoring links to v6-only hosts.
Related errors
- URL must include a host
- URL must include a valid host
- Failed to open URL with default browser launchers; Brave com
- browser_open is not supported on this OS
- URL userinfo is not allowed
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/18fecb9dfed0bc1b.
Report an issue: GitHub.