influxdata/influxdb · error · QueryExecutorError

unable to compose record batches from databases

Error message

unable to compose record batches from databases: {0}

What it means

This QueryExecutorError::DatabasesToRecordBatch variant wraps an ArrowError raised while converting queried database data into Arrow RecordBatches. The executor built result batches across databases and Arrow rejected the operation (schema merge, construction, or concat failure).

Solutions

  1. Check that queried databases have compatible table schemas (same column names and Arrow types)
  2. Run queries against a single database to identify which one's schema breaks composition
  3. Fix schema drift by migrating the offending table's column types
  4. Log the wrapped ArrowError to identify the exact field/type conflict

Example fix

// before
// SELECT * FROM db1.meas, db2.meas — type mismatch on 'value'
// after
// align schemas first:
// ALTER TABLE db2.meas ALTER COLUMN value SET DATA TYPE FLOAT64;
Defensive patterns

Strategy: try-catch

Validate before calling

// verify schema compatibility before cross-database composition
let schemas = dbs.iter().map(|db| get_table_schema(db, table)).collect::<Result<Vec<_>,_>>()?;
let first = &schemas[0];
for s in &schemas[1..] {
    assert_eq!(s.fields(), first.fields(), "schema drift across databases");
}

Type guard

fn is_batch_compose_err(e: &QueryExecutorError) -> Option<&ArrowError> {
    if let QueryExecutorError::DatabasesToRecordBatch(ae) = e { Some(ae) } else { None }
}

Try / catch

match executor.databases_to_record_batch(&dbs) {
    Ok(batches) => batches,
    Err(QueryExecutorError::DatabasesToRecordBatch(ae)) => {
        log::error!("arrow batch composition failed: {ae}");
        Err(QueryExecutorError::DatabasesToRecordBatch(ae))
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Executing a query spanning multiple databases whose resulting schemas cannot be unified into record batches; mismatched column types or field nullability when composing batches.

Common situations: Databases with drifted schemas for the same table name (a column changed type between databases); querying across databases after a migration changed field types; empty vs non-empty batch schema conflicts.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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

Appendix: source

Thrown at influxdb3_internal_api/src/query_executor.rs:31

use iox_query_influxql::show_retention_policies::InfluxQlShowRetentionPolicies;
use iox_query_params::StatementParams;
use schema::INFLUXQL_MEASUREMENT_COLUMN_NAME;
use std::fmt::Debug;
use std::sync::Arc;
use trace::ctx::SpanContext;
use trace::span::{Span, SpanExt};
use trace_http::ctx::RequestLogContext;
use tracker::InstrumentedAsyncOwnedSemaphorePermit;

#[derive(Debug, thiserror::Error)]
pub enum QueryExecutorError {
    #[error("database not found: {db_name}")]
    DatabaseNotFound { db_name: String },
    #[error("error while planning query: {0}")]
    QueryPlanning(#[source] DataFusionError),
    #[error("error while executing plan: {0}")]
    ExecuteStream(#[source] DataFusionError),
    #[error("unable to compose record batches from databases: {0}")]
    DatabasesToRecordBatch(#[source] ArrowError),
    #[error("unable to compose record batches from retention policies: {0}")]
    RetentionPoliciesToRecordBatch(#[source] ArrowError),
    #[error("invokded a method that is not implemented: {0}")]
    MethodNotImplemented(&'static str),
    #[error(transparent)]
    Anyhow(#[from] anyhow::Error),
}

#[async_trait]
pub trait QueryExecutor: QueryDatabase + Debug + Send + Sync + 'static {
    async fn get_db_namespace(
        &self,
        database_name: &str,
        span_ctx: &Option<SpanContext>,
    ) -> Result<Arc<dyn QueryNamespace>, QueryExecutorError> {
        self.namespace(
            database_name,

View on GitHub (pinned to 06200ef96b)