influxdata/influxdb · error · Error

{error_code}

{error_code}

Error message

server responded with error [{code}]: {message}

What it means

Error::ApiError, returned when the InfluxDB 3 server responds with a non-success HTTP status. The variant carries the StatusCode, a human-readable message parsed from the response body, and an optional machine-readable error_code extracted from JSON error responses. This is the server explicitly rejecting the request — not a transport or parsing failure.

Solutions

  1. Read message and error_code fields on the variant to identify the server-side cause
  2. For ApiError with 401/403, fix the token (Authorization: Bearer ...) and its permissions
  3. For 404/422 on queries, verify database name and SQL against the server catalog
  4. For 400 on writes, validate line protocol / payload format before sending
  5. Check server logs for the corresponding request to get full context

Example fix

// before
let resp = client.api_v3_query_sql(sql, ...).await?; // ApiError bubbles up
// after
match client.api_v3_query_sql(sql, ...).await {
    Ok(resp) => resp,
    Err(influxdb3_client::Error::ApiError { code: StatusCode::UNAUTHORIZED, .. }) => {
        refresh_token_and_retry().await
    }
    Err(e) => return Err(e),
}
Defensive patterns

Strategy: type-guard

Validate before calling

// before calling: validate SQL/db name client-side
if db.is_empty() || sql.trim().is_empty() {
    return Err("database and sql are required");
}

Type guard

fn as_api_error(e: &influxdb3_client::Error)
    -> Option<(http::StatusCode, &str, Option<&str>)>
{
    if let influxdb3_client::Error::ApiError { code, message, error_code } = e {
        Some((*code, message.as_str(), error_code.as_deref()))
    } else { None }
}

Try / catch

match result {
    Err(e @ influxdb3_client::Error::ApiError { code, message, error_code }) => {
        match code {
            StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN => reauthenticate().await,
            StatusCode::TOO_MANY_REQUESTS => backoff_and_retry().await,
            _ => log::error!("api error {code} ({error_code:?}): {message}"),
        }
    }
    other => other?,
}

Prevention

When it happens

Trigger: Any Client API call where the server returns 4xx/5xx: invalid SQL in a query, unknown database/table, bad write payload, missing or invalid auth token, resource limits exceeded, or server-side internal errors.

Common situations: Typo'd SQL or nonexistent database in a query (404/422); expired or wrong token (401/403); malformed line-protocol writes (400); hitting the server during startup or under load (503). Match on error_code for programmatic handling.

Related errors


AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19). Data as JSON: /api/errors/8064a320a26be429. Report an issue: GitHub.

Appendix: source

Thrown at influxdb3_client/src/lib.rs:56

        "provided parameter ('{name}') could not be converted \
        to a statment parameter"
    )]
    ConvertQueryParam {
        name: String,
        #[source]
        source: iox_query_params::Error,
    },

    #[error("invalid UTF8 in response: {0}")]
    InvalidUtf8(#[from] FromUtf8Error),

    #[error("failed to parse JSON response: {}", reqwest_description(.0))]
    Json(#[source] reqwest::Error),

    #[error("failed to parse plaintext response: {}", reqwest_description(.0))]
    Text(#[source] reqwest::Error),

    #[error("server responded with error [{code}]: {message}")]
    ApiError {
        code: StatusCode,
        message: String,
        /// Machine-readable error code from JSON error responses, if present.
        error_code: Option<String>,
    },

    #[error("failed to send {method} {url} request: {}", reqwest_description(.source))]
    RequestSend {
        method: Method,
        url: String,
        #[source]
        source: reqwest::Error,
    },

    #[error("failed to build an http client: {}", reqwest_description(.0))]
    Builder(#[source] reqwest::Error),

View on GitHub (pinned to 06200ef96b)