BoundaryML/baml · error
time-of-day fits in i64
Error message
time-of-day fits in i64
What it means
Internal invariant panic in PlainDateTime.to_plain_time: after Euclidean-modulo reduction to one day (NANOS_PER_DAY), the nanosecond-of-day value must mathematically fit in an i64 (0..86,399,999,999,999). i64::try_from().expect() can only fail if the modulo logic is broken or NANOS_PER_DAY is corrupted.
Source
Thrown at baml_language/crates/bex_vm/src/package_baml/time.rs:342
"PlainDateTime.to_plain_date: value is outside the supported year range"
.to_string(),
)
})?;
Ok(copy::time::PlainDate { _days: days }.to_value(vm))
}
fn to_plain_time(vm: &mut BexVm, plaindatetime: &Value) -> Value {
let civil = {
let instance = vm
.as_instance(plaindatetime)
.expect("PlainDateTime.to_plain_time: expected PlainDateTime instance");
view::time::PlainDateTime { instance }._nanoseconds()
};
// Euclidean modulo one day is exact regardless of the bigint's
// magnitude or sign, and the result always fits in an i64.
let day = num_bigint::BigInt::from(NANOS_PER_DAY);
let time_ns = ((&*civil % &day) + &day) % &day;
let time_ns = i64::try_from(time_ns).expect("time-of-day fits in i64");
copy::time::PlainTime {
_nanoseconds: time_ns,
}
.to_value(vm)
}
fn year(plaindatetime: &view::time::PlainDateTime<'_>) -> Result<i64, VmRustFnError> {
Ok(i64::from(
civil_datetime(&plaindatetime._nanoseconds(), "PlainDateTime.year")?.year(),
))
}
fn month(plaindatetime: &view::time::PlainDateTime<'_>) -> Result<i64, VmRustFnError> {
Ok(i64::from(u8::from(
civil_datetime(&plaindatetime._nanoseconds(), "PlainDateTime.month")?.month(),
)))
}
View on GitHub (pinned to bd85ce9dee)
Solutions
- Report to maintainers with the exact datetime value that triggered it.
- Verify the PlainDateTime instance was not constructed via internal/private field access.
- Check for VM/version mismatch; upgrade to the latest bex_vm build.
Defensive patterns
Strategy: fallback
Validate before calling
// Validate the instance was produced by the library before calling to_plain_time()
fn is_valid_plain_datetime(v: &Value, vm: &BexVm) -> bool {
vm.as_instance(v).map(|i| i.class() == "PlainDateTime").unwrap_or(false)
} Type guard
fn as_plain_datetime<'a>(vm: &'a BexVm, v: &Value) -> Option<InstanceRef<'a>> {
vm.as_instance(v).ok().filter(|i| i.class() == "PlainDateTime")
} Try / catch
// Rust caller: use catch_unwind around VM invocations to convert panics into errors std::panic::catch_unwind(|| vm_call_to_plain_time(...)).unwrap_or_else(|_| Err(VmError::Internal))
Prevention
- Use only library-produced PlainDateTime values.
- Keep the VM updated; this panic signals a VM bug, not input error.
- Report reproductions to maintainers with the exact value.
When it happens
Trigger: Essentially unreachable from user code; would require a corrupted PlainDateTime nanosecond bigint or a bug in the reduction arithmetic.
Common situations: Hit only during development of the VM itself, or if a bug allows out-of-spec bigint states into PlainDateTime 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
- sys_op callee must resolve to a statically-known global func
- exhaustive realized-leaf template classification
- interface index {} is not an Object::Interface
- interface `{}` declares no method `{}` for its default
- type-alias offset fits u32
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/2b70452507f6346d.
Report an issue: GitHub.