risingwavelabs/risingwave · error · SinkError

Insert error: , error url

Error message

Insert error: {:?}, error url: {:?}

What it means

After a Doris stream-load insert finishes, the response JSON is parsed into DorisInsertResultResponse and its `status` field is checked against DORIS_SUCCESS_STATUS. A non-success status raises this error with the failure message and the error URL where Doris stores detailed logs.

Solutions

  1. Open the error URL printed in the message to inspect per-row failure reasons from Doris.
  2. Align the RisingWave sink schema with the Doris table (names, order, types).
  3. Increase `max_filter_ratio` only if tolerable, or clean the offending data.
  4. Retry the sink after fixing; transient BE issues may also cause Fail status.
Defensive patterns

Strategy: validation

Validate before calling

// precheck schema alignment
// ensure RisingWave sink columns match Doris table columns in name, order, and type

Try / catch

match inserter.finish().await {
    Err(SinkError::DorisStarrocksConnect(e)) if e.to_string().contains("Insert error") => {
        if let Some(url) = extract_err_url(&e.to_string()) {
            eprintln!("doris load failed, details at: {url}");
        }
    }
    other => other?,
}

Prevention

When it happens

Trigger: A stream-load batch insert whose result status is not in DORIS_SUCCESS_STATUS (e.g. 'Fail'), typically due to schema mismatch, bad data format, or load limit violations.

Common situations: Column count/type mismatch between RisingWave and the Doris table; malformed rows failing parsing; exceeding max_filter_ratio with too many error rows; Doris tablet/BE issues.

Related errors


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

Appendix: source

Thrown at src/connector/src/sink/doris.rs:665

    pub async fn write(&mut self, data: Bytes) -> Result<()> {
        let mut data_build = BytesMut::new();
        if self.is_first_record {
            self.is_first_record = false;
        } else {
            data_build.put_slice("\n".as_bytes());
        }
        data_build.put_slice(&data);
        self.insert.write(data_build.into()).await?;
        Ok(())
    }

    pub async fn finish(self) -> Result<DorisInsertResultResponse> {
        let raw = self.insert.finish().await?;
        let res: DorisInsertResultResponse = serde_json::from_slice(&raw)
            .map_err(|err| SinkError::DorisStarrocksConnect(err.into()))?;

        if !DORIS_SUCCESS_STATUS.contains(&res.status.as_str()) {
            return Err(SinkError::DorisStarrocksConnect(anyhow::anyhow!(
                "Insert error: {:?}, error url: {:?}",
                res.message,
                res.err_url
            )));
        };
        Ok(res)
    }
}

View on GitHub (pinned to 6469eb736d)