nautechsystems/nautilus_trader · error · anyhow::Error

Unknown data type: {type_name}; custom decode only allowed i

Error message

Unknown data type: {type_name}; custom decode only allowed in custom data context

What it means

decode_batch_to_data raises this when the batch's type name is not a known custom type, indicating the batch was routed to the custom decoder path but its type is not registered for custom decoding. Custom decode is only allowed for types in the custom data context, so foreign/unknown types are rejected here.

Source

Thrown at crates/persistence/src/backend/custom.rs:221

        "IndexPriceUpdate" | "index_price_updates" => {
            Ok(IndexPriceUpdate::decode_data_batch(metadata, batch)?)
        }
        "OptionGreeks" | "option_greeks" => Ok(OptionGreeks::decode_data_batch(metadata, batch)?),
        "InstrumentClose" | "instrument_closes" => {
            Ok(InstrumentClose::decode_data_batch(metadata, batch)?)
        }
        _ => {
            if allow_custom_fallback {
                #[cfg(feature = "python")]
                {
                    return Ok(CustomDataDecoder::decode_data_batch(metadata, batch)?);
                }
                #[cfg(not(feature = "python"))]
                {
                    anyhow::bail!("Unknown data type: {type_name}");
                }
            }
            anyhow::bail!(
                "Unknown data type: {type_name}; custom decode only allowed in custom data context"
            )
        }
    }
}

/// Decodes multiple `RecordBatches` (e.g. from custom data files) into a single `Vec<Data>`.
/// Optionally replaces `ts_init` column with `ts_event` before decoding each batch.
///
/// # Errors
///
/// Returns an error if any batch fails to decode.
pub fn decode_custom_batches_to_data(
    batches: Vec<RecordBatch>,
    use_ts_event_for_ts_init: bool,
) -> anyhow::Result<Vec<Data>> {
    let mut file_data = Vec::new();
    let schema = batches

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure only batches with registered custom type names go through decode_custom_batches_to_data; decode built-in types via their normal path.
  2. Register the custom data type before decoding so the type name resolves.
  3. Verify the type_name stored in the Parquet metadata matches the registered custom type exactly (check for typos/case).
  4. Re-export the data from the original writer version if metadata names differ.
Defensive patterns

Strategy: validation

Validate before calling

// route batches by type before decoding
let (custom, builtin): (Vec<_>, Vec<_>) = batches
    .into_iter()
    .partition(|b| batch_type_name(b).starts_with("custom/"));
// decode custom via decode_custom_batches_to_data, builtin via the standard path

Type guard

fn is_custom_batch(b: &RecordBatchMeta) -> bool {
    b.type_name().starts_with("custom/") && is_registered_custom_type(b.type_name())
}

Try / catch

match decode_custom_batches_to_data(batches) {
    Err(e) if e.to_string().contains("custom decode only allowed") => {
        // reroute batch to the built-in decode path
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling decode_custom_batches_to_data with record batches whose metadata type_name is not a registered custom type (wrong context routing, mixed batches, or a type name typo in file metadata).

Common situations: Passing built-in type batches (Quote/Trade) into the custom decode path accidentally; catalogs written by a different version with unregistered custom types; manually edited or migrated Parquet metadata.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/3f6596824018fe8e. Report an issue: GitHub.