BoundaryML/baml · error
TimeZoneOffset.from_duration: expected Duration instance
Error message
TimeZoneOffset.from_duration: expected Duration instance
What it means
This panic occurs in TimeZoneOffset.from_duration when the argument is not a Duration object instance allocated by the VM. vm.as_instance().expect() panics for nulls, numbers, strings, or objects of any other class instead of returning an error.
Source
Thrown at baml_language/crates/bex_vm/src/package_baml/time.rs:449
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)
.ok_or_else(|| {
invalid_argument(
"TimeZoneOffset out of range: must be within ±24 hours".to_string(),
)
})?;
Ok(copy::time::TimeZoneOffset {
_nanoseconds: offset_ns,
}
.to_value(vm))
}
}
impl BamlClassTimeZonedDateTime for PackageBamlImpl {View on GitHub (pinned to bd85ce9dee)
Solutions
- Construct a Duration first (e.g. Duration.of_hours(5)) and pass that instance.
- Parse strings with Duration.parse before conversion.
- Type-check the argument before the call.
- Report a bug if a real Duration instance triggers the panic.
Example fix
// before TimeZoneOffset.from_duration(5 * 3600 * 1_000_000_000) // int, panics // after TimeZoneOffset.from_duration(Duration.of_hours(5))
Defensive patterns
Strategy: type-guard
Validate before calling
fn is_duration(v: &Value, vm: &BexVm) -> bool {
vm.as_instance(v).map(|i| i.class() == "Duration").unwrap_or(false)
} Type guard
fn as_duration<'a>(vm: &'a BexVm, v: &Value) -> Option<InstanceRef<'a>> {
vm.as_instance(v).ok().filter(|i| i.class() == "Duration")
} Try / catch
// BAML side
if v is Duration { TimeZoneOffset.from_duration(v) } else { Error("expected Duration") } Prevention
- Pass Duration instances, not raw nanosecond ints or ISO strings.
- Parse strings with Duration.parse first.
- Re-hydrate Duration instances after JSON deserialization.
When it happens
Trigger: Calling TimeZoneOffset.from_duration() with a non-Duration value: an int of nanoseconds, a string like 'PT5H', null, or a PlainTime/other instance.
Common situations: Passing a raw nanosecond count or ISO-8601 duration string instead of a Duration instance; deserialized durations losing instance identity through JSON.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- ai.Prompt._data must contain baml_builtins2::PromptAst
- PlainDateTime.to_plain_time: expected PlainDateTime instance
- offset fits in BAML int
- offset fits in BAML int
- array access should be either map or array.
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/e84f171e8e87b62a.
Report an issue: GitHub.