dbt-labs/dbt-core · error

invalid serialized time precision

Error message

invalid serialized time precision

What it means

This panic comes from `parse::<u8>().expect("invalid serialized time precision")` in `is_time`. The library encodes time precision in Arrow field names as `time:<u8>` (e.g. `time:3` for millisecond); when the digits after the prefix fail to parse as u8 (or the value exceeds TimePrecision's bounds), the parse fails and the code panics. Unlike the prefix expect, this one IS reachable with malformed serialized data.

Source

Thrown at crates/dbt-adapter/src/sql_types.rs:1069

        pub fn unwrap(self) -> TimePrecision {
            match self {
                IsTimestamp::No => panic!("Cannot unwrap IsTimestamp::No"),
                IsTimestamp::Yes(precision) => precision,
            }
        }
    }

    pub fn is_time(data_type: &DataType) -> IsTimestamp {
        match data_type {
            DataType::FixedSizeList(field, 1) if field.name().starts_with("time:") => {
                IsTimestamp::Yes(TimePrecision::new(
                    field
                        .name()
                        .strip_prefix("time:")
                        .expect("string prefix checked")
                        .parse::<u8>()
                        .expect("invalid serialized time precision"),
                ))
            }
            _ => IsTimestamp::No,
        }
    }

    pub fn is_timestamp_ntz(data_type: &DataType) -> IsTimestamp {
        match data_type {
            DataType::FixedSizeList(field, 1) if field.name().starts_with("timestamp_ntz:") => {
                IsTimestamp::Yes(TimePrecision::new(
                    field
                        .name()
                        .strip_prefix("timestamp_ntz:")
                        .expect("string prefix checked")
                        .parse::<u8>()
                        .expect("invalid serialized timestamp precision"),
                ))
            }

View on GitHub (pinned to 0267ce9170)

Solutions

  1. Fix the Arrow field name so the precision suffix is a valid u8 within the supported range (0, 3, 6, or 9 — matching second/millisecond/microsecond/nanosecond).
  2. Locate where the field name is serialized (search for "time:" writers / from-arrow conversions) and correct the encoder, not just the fixture.
  3. If the offending data comes from an old recording or IPC fixture, regenerate it with the current dbt version instead of patching by hand.
  4. For resilience, replace the expect with a parse that returns IsTimestamp::No or a descriptive error rather than panicking on malformed upstream metadata.

Example fix

// before
.parse::<u8>()
.expect("invalid serialized time precision"),
// after
.parse::<u8>().unwrap_or_else(|_| panic!(
    "invalid serialized time precision in field '{}' (expected 'time:<0|3|6|9>')",
    field.name()))
Defensive patterns

Strategy: validation

Validate before calling

fn validate_time_field_name(name: &str) -> Result<u8, String> {
    let prec = name.strip_prefix("time:")
        .ok_or_else(|| format!("missing 'time:' prefix: {name}"))?;
    prec.parse::<u8>().map_err(|e| format!("bad precision in '{name}': {e}"))
}
// call before passing the DataType to is_time
assert!(validate_time_field_name(field.name()).is_ok());

Type guard

fn well_formed_time_type(dt: &DataType) -> bool {
    matches!(dt, DataType::FixedSizeList(f, 1)
        if f.name().strip_prefix("time:").is_some_and(|s| s.parse::<u8>().is_ok()))
}

Try / catch

// panic cannot be caught in Rust; run the conversion in a subprocess/isolated test if untrusted schemas must be tolerated
let result = std::panic::catch_unwind(|| is_time(&data_type));

Prevention

When it happens

Trigger: Calling `is_time(&DataType::FixedSizeList(field, 1))` where `field.name()` matches `time:*` but the remainder is not a valid u8 — e.g. `time:abc`, `time:` (empty), `time:300`, `time:-1`, or `time:3.5`. Also triggered by fixture/IPC files whose field names were hand-edited or produced by an older/different serializer.

Common situations: Hand-crafted Arrow schemas in tests or recordings, schema files migrated between dbt versions where the precision encoding changed, corrupted round-tripped metadata, or someone writing `time:9`/`time:100` assuming arbitrary precision digits are allowed.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of dbt-labs/dbt-core@0267ce9170 (2026-09-07). Data as JSON: /api/errors/de4c319c33402b5d. Report an issue: GitHub.