risingwavelabs/risingwave · error · SinkError::ElasticSearchOpenSearch

SinkError::ElasticSearchOpenSearch(anyhow!(err))

Error message

SinkError::ElasticSearchOpenSearch(anyhow!(err))

What it means

RisingWave converts any ::elasticsearch::Error into the ElasticSearchOpenSearch SinkError variant. It means an Elasticsearch client operation (index, bulk, connection) failed and the driver error was wrapped into an anyhow error.

Source

Thrown at src/connector/src/sink/mod.rs:1297

        SinkError::Remote(anyhow!(value))
    }
}

impl From<RedisError> for SinkError {
    fn from(value: RedisError) -> Self {
        SinkError::Redis(value.to_report_string())
    }
}

impl From<tiberius::error::Error> for SinkError {
    fn from(err: tiberius::error::Error) -> Self {
        SinkError::SqlServer(anyhow!(err))
    }
}

impl From<::elasticsearch::Error> for SinkError {
    fn from(err: ::elasticsearch::Error) -> Self {
        SinkError::ElasticSearchOpenSearch(anyhow!(err))
    }
}

impl From<::opensearch::Error> for SinkError {
    fn from(err: ::opensearch::Error) -> Self {
        SinkError::ElasticSearchOpenSearch(anyhow!(err))
    }
}

impl From<tokio_postgres::Error> for SinkError {
    fn from(err: tokio_postgres::Error) -> Self {
        SinkError::Postgres(anyhow!(err))
    }
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeMap;

View on GitHub (pinned to 6469eb736d)

Solutions

  1. Check cluster health and reachability: GET _cluster/health from the sink URL.
  2. Inspect the wrapped HTTP status/body in the error message; fix mapping conflicts by updating the index mapping or coercing data.
  3. Verify credentials/API key if security (X-Pack) is enabled on the cluster.
  4. Reduce bulk batch size if 429/413 errors appear.
  5. Align the elasticsearch crate major version with the cluster version.
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-check cluster availability before sink creation
curl -fsS -u "$ES_USER:$ES_PASS" "$ELASTIC_URL/_cluster/health" | jq -e '.status'

Type guard

fn is_retryable_es_error(err: &elasticsearch::Error) -> bool {
    use elasticsearch::Error::*;
    matches!(err, Io(_) | ServerError(_))
}

Try / catch

// inspect the wrapped response status before deciding retry
match err {
    e if e.to_string().contains("429") || e.to_string().contains("413") => retry_with_backoff(),
    _ => alert_and_fail(),
}

Prevention

When it happens

Trigger: Any elasticsearch crate error during sink writes: failed HTTP request, non-success Elasticsearch response, connection/transport failure, or deserialization failure of the response.

Common situations: Elasticsearch cluster unreachable or restarting, index mapping conflicts (wrong field type), bulk request too large, authentication against a secured cluster missing, or elasticsearch crate version mismatch with 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/9c92cbfa7263a0ae. Report an issue: GitHub.