risingwavelabs/risingwave · error · SinkError

Can't get doris BE url in header

Error message

Can't get doris BE url in header

What it means

Doris stream load uses a two-step redirect: the FE answers 307 TEMPORARY_REDIRECT with the BE URL in the `location` header. If a 307 arrives without that header, or the header value is not valid UTF-8, try_get_be_url raises this error because the actual BE endpoint cannot be determined.

Source

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

    pub fn build(self) -> HashMap<String, String> {
        self.header
    }
}

/// Try getting BE url from a redirected response, returning `Ok(None)` indicates this request does
/// not redirect.
///
/// The reason we handle the redirection manually is that if we let `reqwest` handle the redirection
/// automatically, it will remove sensitive headers (such as Authorization) during the redirection,
/// and there's no way to prevent this behavior.
fn try_get_be_url(resp: &Response, fe_host: &str) -> Result<Option<Url>> {
    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

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Check any proxy/LB between RisingWave and Doris FE preserves the Location header on 307 responses.
  2. Verify the Doris FE is healthy and reachable directly (bypass proxies).
  3. Inspect the raw response headers with curl -v against the stream-load endpoint.
  4. Upgrade Doris if the FE is known to emit broken redirects.
Defensive patterns

Strategy: try-catch

Try / catch

match send_stream_load_request(&mut req).await {
    Err(SinkError::DorisStarrocksConnect(e)) if e.to_string().contains("Can't get doris BE url in header") => {
        eprintln!("FE sent 307 without a usable Location header; check proxies");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Receiving HTTP 307 from the Doris FE with no `location` header, or a non-ASCII/non-UTF-8 location value, during send_stream_load_request or connector build.

Common situations: Misconfigured proxy/load balancer stripping the Location header; malformed FE redirect responses; non-ASCII hostnames in the cluster.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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