influxdata/influxdb · error · Error
Unexpected schema change
Error message
Unexpected schema change
What it means
Error variant `UnexpectedSchemaChange` thrown when the Arrow schema observed mid-stream differs from the schema the client established (typically from the initial schema message or a previous batch). Flight result streams must be schema-stable; the client treats any divergence as malformed data.
Solutions
- Re-run the query to get a fresh, consistent stream
- Check whether the source table's schema was altered during the query and re-plan after migration completes
- Make the query's output schema deterministic (explicit column list, casts)
- Upgrade client/server — some mid-stream schema handling was relaxed/fixed in newer IOx versions
Example fix
// before
let batches = client.query("SELECT * FROM measurements").await?;
// after
let batches = client.query("SELECT time, region, value FROM measurements").await?; // fixed output schema Defensive patterns
Strategy: retry
Validate before calling
// verify the query yields a fixed schema: // SELECT time, region, value FROM ... instead of SELECT *
Type guard
fn is_unexpected_schema_change(e: &Error) -> bool {
matches!(e, Error::UnexpectedSchemaChange)
} Try / catch
match client.query(sql).await {
Err(Error::UnexpectedSchemaChange) => {
// re-issue the query for a fresh consistent stream
client.query(sql).await
}
other => other,
} Prevention
- Use explicit column lists and casts so query output schema is stable
- Avoid schema migrations on tables during long-running streams
- Re-run queries rather than resuming a stream after a schema change
- Monitor for concurrent ALTER operations on queried tables
When it happens
Trigger: Streaming query results when a later RecordBatch in the same Flight stream arrives with different fields, types, or field order than the stream's declared schema — e.g. the underlying IOx query returned evolving/changing schemas across batches.
Common situations: Queries spanning partitions or tables with altered schema; server-side schema migration occurring while a long-running stream is open; writing a custom query whose output columns change (e.g. via dynamic SQL).
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- ' ' is a reserved column
- By the point that we're doing partitioning, we should've…
- cannot add column because it already exists with type
- column id in series key should be valid
- column type mismatch for column
AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19).
Data as JSON: /api/errors/6dbbebf3195ce904.
Report an issue: GitHub.
Appendix: source
Thrown at core/influxdb_iox_client/src/client/flight/mod.rs:76
/// Arrow Flight handshake failed.
#[error("Handshake failed: {0}")]
HandshakeFailed(String),
/// Serializing the protobuf structs into bytes failed.
#[error(transparent)]
Serialization(#[from] prost::EncodeError),
/// Deserializing the protobuf structs from bytes failed.
#[error(transparent)]
Deserialization(#[from] prost::DecodeError),
/// Unknown IPC message type.
#[error("Unknown IPC message type: {0:?}")]
UnknownMessageType(ipc::MessageHeader),
/// Unexpected schema change.
#[error("Unexpected schema change")]
UnexpectedSchemaChange,
}
impl Error {
/// Extracts the underlying tonic status, if any
pub fn tonic_status(&self) -> Option<&Status> {
if let Self::ArrowFlightError(FlightError::Tonic(status)) = self {
Some(status)
} else {
None
}
}
}
impl From<Status> for Error {
fn from(status: Status) -> Self {
Self::ArrowFlightError(status.into())
}View on GitHub (pinned to 06200ef96b)