influxdata/influxdb · critical · Error

Unrecoverable data loss or corruption

Error message

Unrecoverable data loss or corruption: {0}

What it means

This Error variant maps a gRPC Status with code DATA_LOSS into "Unrecoverable data loss or corruption: {0}". The server (or transport) has determined that data was lost or corrupted and the operation cannot be retried successfully. The From<Status> impl in core/influxdb_iox_client/src/client/error.rs produces it; the wrapped ServerError<()> carries any server-provided detail.

Solutions

  1. Do not blindly retry — DATA_LOSS indicates a non-transient condition.
  2. Inspect server logs and storage health to identify the corrupted segment or object.
  3. Restore the affected data from backups/replication and re-run the operation.
  4. Escalate to the storage/ops team; this usually requires server-side remediation, not client changes.
Defensive patterns

Strategy: fallback

Type guard

fn is_data_loss(e: &client::Error) -> bool {
    matches!(e, client::Error::DataLoss(_))
}

Try / catch

match res {
    Err(Error::DataLoss(se)) => {
        page_storage_ops(&format!("data loss: {se}"));
        // switch to a backup/replica data path if available
    }
    other => other.map_err(Into::into),
}

Prevention

When it happens

Trigger: Server detects corruption in persisted data (segment/WAL/catalog) while serving a read or write; a storage backend reports unrecoverable read errors; transport-level corruption flagged mid-stream.

Common situations: Failed disks or truncated Parquet/WAL files on an IOx node; restoring from an incomplete backup; hardware faults in the object store backing the cluster.

Related errors


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

Appendix: source

Thrown at core/influxdb_iox_client/src/client/error.rs:108

    #[error("The system is not in a state required for the operation's execution: {0}")]
    FailedPrecondition(Box<ServerError<PreconditionViolation>>),

    #[error("The operation was aborted: {0}")]
    Aborted(ServerError<()>),

    #[error("Operation was attempted past the valid range: {0}")]
    OutOfRange(ServerError<()>),

    #[error("Operation is not implemented or supported: {0}")]
    Unimplemented(ServerError<()>),

    #[error("Internal error: {0}")]
    Internal(ServerError<()>),

    #[error("The service is currently unavailable: {0}")]
    Unavailable(ServerError<()>),

    #[error("Unrecoverable data loss or corruption: {0}")]
    DataLoss(ServerError<()>),

    #[error("The request does not have valid authentication credentials: {0}")]
    Unauthenticated(ServerError<()>),

    #[error("Received an invalid response from the server: {0}")]
    InvalidResponse(#[from] FieldViolation),

    #[error("An unexpected error occurred in the client library: {0}")]
    Client(StdError),
}

impl From<Status> for Error {
    fn from(s: Status) -> Self {
        match s.code() {
            Code::Ok => Self::Client("status is not an error".into()),
            Code::Cancelled => Self::Cancelled(parse_status(s)),
            Code::Unknown => Self::Unknown(parse_status(s)),

View on GitHub (pinned to 06200ef96b)