BoundaryML/baml · error

second fits in u8

Error message

second fits in u8

What it means

Internal invariant panic during PlainTime string formatting: the second bucket ns / NANOS_PER_SECOND % 60 must be 0..59, so the u8::try_from().expect() can only fail if the surrounding arithmetic is broken.

Solutions

  1. Report with the failing value.
  2. Rebuild with consistent constants.
  3. Do not construct PlainTime via private fields.
Defensive patterns

Strategy: validation

Validate before calling

fn plain_time_in_range(ns: i64) -> bool { (0..86_400_000_000_000).contains(&ns) }

Try / catch

std::panic::catch_unwind(|| plaintime_to_string(pt)).unwrap_or_else(|_| Err(FormatError::Internal))

Prevention

When it happens

Trigger: Unreachable under normal operation; requires corrupted nanosecond state or inconsistent time constants.

Common situations: VM development or corrupted PlainTime internals.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/99fd3f4100a0ee07. Report an issue: GitHub.

Appendix: source

Thrown at baml_language/crates/bex_vm/src/package_baml/time.rs:436

        let time_ns = i64::from(parsed.hour()) * NANOS_PER_HOUR
            + i64::from(parsed.minute()) * NANOS_PER_MINUTE
            + i64::from(parsed.second()) * NANOS_PER_SECOND
            + i64::from(parsed.nanosecond());
        Ok(copy::time::PlainTime {
            _nanoseconds: time_ns,
        }
        .to_value(vm))
    }

    fn _to_string_impl(plaintime: &view::time::PlainTime<'_>) -> bex_str::BexStr {
        // Normalize manually-constructed out-of-range values into [0, 24h).
        let ns = plaintime._nanoseconds().rem_euclid(MAX_TZ_OFFSET_NS);
        let mut out = String::new();
        format_clock_into(
            &mut out,
            u8::try_from(ns / NANOS_PER_HOUR).expect("hour fits in u8"),
            u8::try_from(ns / NANOS_PER_MINUTE % 60).expect("minute fits in u8"),
            u8::try_from(ns / NANOS_PER_SECOND % 60).expect("second fits in u8"),
            u32::try_from(ns % NANOS_PER_SECOND).expect("subsecond fits in u32"),
        );
        bex_str::BexStr::from(out)
    }
}

#[allow(clippy::used_underscore_items)] // Autogenerated from private BAML fields
impl BamlClassTimeTimeZoneOffset for PackageBamlImpl {
    fn from_duration(vm: &mut BexVm, duration: &Value) -> Result<Value, VmRustFnError> {
        let nanos = {
            let instance = vm
                .as_instance(duration)
                .expect("TimeZoneOffset.from_duration: expected Duration instance");
            view::time::Duration { instance }._nanoseconds()
        };
        let offset_ns = i64::try_from(&*nanos)
            .ok()
            .filter(|ns| ns.abs() <= MAX_TZ_OFFSET_NS)

View on GitHub (pinned to bd85ce9dee)