risingwavelabs/risingwave · error · SinkError

Can't get be host from url

Error message

Can't get be host from url

What it means

After parsing the BE redirect URL, the connector needs the BE host to apply a localhost-rewrite rule (a BE advertising 127.0.0.1 is replaced with the FE host). If Url::parse succeeded but host_str() returns None, the URL has no host component and this error is thrown.

Source

Thrown at src/connector/src/sink/doris_starrocks_connector.rs:204

    match resp.status() {
        StatusCode::TEMPORARY_REDIRECT => {
            let be_url = resp
                .headers()
                .get("location")
                .ok_or_else(|| {
                    SinkError::DorisStarrocksConnect(anyhow!("Can't get doris BE url in header",))
                })?
                .to_str()
                .context("Can't get doris BE url in header")
                .map_err(SinkError::DorisStarrocksConnect)?
                .to_owned();

            let mut parsed_be_url = Url::parse(&be_url)
                .map_err(|err| SinkError::DorisStarrocksConnect(anyhow!(err)))?;

            if fe_host != LOCALHOST && fe_host != LOCALHOST_IP {
                let be_host = parsed_be_url.host_str().ok_or_else(|| {
                    SinkError::DorisStarrocksConnect(anyhow!("Can't get be host from url"))
                })?;

                if be_host == LOCALHOST || be_host == LOCALHOST_IP {
                    // if be host is 127.0.0.1, we may can't connect to it directly,
                    // so replace it with fe host
                    parsed_be_url
                        .set_host(Some(fe_host))
                        .map_err(|err| SinkError::DorisStarrocksConnect(anyhow!(err)))?;
                }
            }
            Ok(Some(parsed_be_url))
        }
        StatusCode::OK => {
            // Some of the `StarRocks` transactional APIs will respond directly from FE. For example,
            // the request to `/api/transaction/commit` endpoint does not seem to redirect to BE.
            // In this case, the request should be treated as finished.
            Ok(None)
        }

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Inspect the Location header returned by the FE and ensure it is a full URL with host.
  2. Fix BE `heartbeat_service_port`/advertised address configuration in Doris so redirects use proper hostnames.
  3. Connect to the FE directly rather than through a rewriting proxy.
Defensive patterns

Strategy: try-catch

Type guard

fn url_has_host(u: &str) -> bool {
    url::Url::parse(u).ok().and_then(|u| u.host_str().map(|_| true)).unwrap_or(false)
}

Try / catch

match try_get_be_url(resp).await {
    Err(SinkError::DorisStarrocksConnect(e)) if e.to_string().contains("Can't get be host from url") => {
        eprintln!("BE redirect URL missing host: {e}");
    }
    other => other?,
}

Prevention

When it happens

Trigger: The Doris FE's 307 location header contains a URL without a host (e.g. a relative path or malformed absolute URL) while the FE host itself is not localhost.

Common situations: Doris misconfiguration advertising bad BE addresses; custom DNS/ingress setups returning odd redirects; corrupted location headers.

Understand the failure class

Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.

Related errors


AI-assisted analysis of risingwavelabs/risingwave@6469eb736d (2026-09-11). Data as JSON: /api/errors/d1c3e2dfbcac428a. Report an issue: GitHub.