BoundaryML/baml · error

minute fits in u8

Error message

minute fits in u8

What it means

Internal invariant panic during PlainTime string formatting: the minute bucket ns / NANOS_PER_MINUTE % 60 must be 0..59 and therefore fit in u8. The expect() failing indicates broken arithmetic/constants, since the modulo bounds the value by construction.

Solutions

  1. Report to maintainers with the failing value.
  2. Rebuild the crate so constants are consistent.
  3. Avoid touching private _nanoseconds fields directly.
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 with correct code; triggered only if MAX_TZ_OFFSET_NS or NANOS_PER_* constants are inconsistent or the nanosecond value is corrupt.

Common situations: VM development, constant refactors, or corrupted internal state.

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/42fd397ea72d891a. Report an issue: GitHub.

Appendix: source

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

        })?;
        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()

View on GitHub (pinned to bd85ce9dee)