t8y2/dbx · error
invalid TDengine host
Error message
invalid TDengine host
What it means
Thrown in `build_from_fields` when the trimmed host value cannot be installed into the URL: if it parses as an IP address, `set_ip_host` failed; otherwise `set_host(Some(host))` rejected it as not a valid host per RFC 3986. Defaults (DEFAULT_HOST) are used only for empty input, so a non-empty but malformed host reaches Url and fails there.
Source
Thrown at agents/drivers/tdengine/src/config.rs:55
set_query_param(&mut url, "tls_ca", params.ca_cert_path.trim());
}
let database = url
.path_segments()
.and_then(|mut segments| segments.find(|segment| !segment.is_empty()))
.map(|segment| percent_decode_str(segment).decode_utf8_lossy().into_owned())
.unwrap_or_default();
Ok(BuiltDsn { value: url.into(), database })
}
fn build_from_fields(params: &ConnectParams) -> Result<Url> {
let scheme = if params.ssl { "wss" } else { "ws" };
let host = if params.host.trim().is_empty() { DEFAULT_HOST } else { params.host.trim() };
let port = if params.port == 0 { DEFAULT_PORT } else { params.port };
let username = if params.username.is_empty() { DEFAULT_USER } else { ¶ms.username };
let password = if params.password.is_empty() { DEFAULT_PASSWORD } else { ¶ms.password };
let mut url = Url::parse(&format!("{scheme}://{DEFAULT_HOST}:{port}/"))?;
if let Ok(address) = host.parse::<IpAddr>() {
url.set_ip_host(address).map_err(|_| anyhow::anyhow!("invalid TDengine host"))?;
} else {
url.set_host(Some(host)).map_err(|_| anyhow::anyhow!("invalid TDengine host"))?;
}
url.set_username(username).map_err(|_| anyhow::anyhow!("invalid TDengine username"))?;
url.set_password(Some(password)).map_err(|_| anyhow::anyhow!("invalid TDengine password"))?;
if !params.database.trim().is_empty() {
url.set_path(&format!("/{}", params.database.trim()));
}
Ok(url)
}
fn apply_connection_fields(url: &mut Url, params: &ConnectParams) -> Result<()> {
if url.username().is_empty() {
let username = if params.username.is_empty() { DEFAULT_USER } else { ¶ms.username };
url.set_username(username).map_err(|_| anyhow::anyhow!("invalid TDengine username"))?;
}
if url.password().is_none() {
let password = if params.password.is_empty() { DEFAULT_PASSWORD } else { ¶ms.password };View on GitHub (pinned to c0390bff16)
Solutions
- Set host to a bare hostname or IP only: no scheme, no port, no path (use the port field for the port).
- Strip scheme prefixes and paths: convert "http://host:6041" to host="host", port=6041.
- For IPv6, pass the address so set_ip_host accepts it (or use the standard bracketed form the parser expects).
- Trim whitespace/quotes from the host env var or config value before constructing params.
Example fix
// before
let params = ConnectionParams { host: "http://tdengine:6041".into(), .. };
// after
let params = ConnectionParams { host: "tdengine".into(), port: 6041, .. }; Defensive patterns
Strategy: validation
Validate before calling
fn validate_host(host: &str) -> Result<(), String> {
let h = host.trim();
if h.is_empty() {
return Ok(()); // falls back to DEFAULT_HOST
}
if h.contains("://") || h.contains('/') || h.contains('@') || h.contains(' ') {
return Err(format!("host must be a bare hostname or IP, got: {h}"));
}
if h.parse::<std::net::IpAddr>().is_ok() || h.parse::<std::net::ToSocketAddrs>().is_ok() {
Ok(())
} else {
Err(format!("invalid TDengine host: {h}"))
}
} Type guard
fn is_bare_host(s: &str) -> bool {
let h = s.trim();
!h.is_empty()
&& !h.contains("://")
&& !h.contains('/')
&& !h.contains('@')
&& (h.parse::<std::net::IpAddr>().is_ok()
|| h.split('.').count() > 1
|| h == "localhost")
} Prevention
- Keep host and port in separate config fields; never embed the port or scheme in host.
- Strip any "http://" or "https://" prefix when importing configs from other tools.
- Trim whitespace and shell quotes from host env vars.
- Write IPv6 addresses in bracketed/valid form and test the DSN at startup.
When it happens
Trigger: Passing a host string containing spaces, underscores in invalid positions, a scheme/protocol prefix like "http://host", userinfo, a path ("host/db"), or an invalid IPv6 literal (not bracketed correctly); also an IP literal that url::set_ip_host rejects.
Common situations: Pasting "http://localhost:6041" into a host-only config field; copying "host:port" including the port into the host field; trailing slashes or paths in the host; environment variables with stray whitespace/quotes from shell interpolation; IPv6 addresses written without brackets.
Related errors
- failed to enable TLS in TDengine connection URL
- Kafka broker does not support " + op.opType() + " config ope
- request.timeout.ms must be a positive integer
- ${name} must be a positive integer
- token contains trailing data
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/c795a415a0ac9584.
Report an issue: GitHub.