BoundaryML/baml · error

offset fits in BAML int

Error message

offset fits in BAML int

What it means

Internal invariant panic when parsing a ZonedDateTime: the numeric UTC offset (offset_ns) was already validated to be within ±24h (MAX_TZ_OFFSET_NS), so it must fit in a BAML int (i64-backed). Value::try_int().expect() failing means the earlier bound check was bypassed or corrupted.

Source

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

                (&full[..open], Some(annotation.to_string()))
            }
            _ => (full, None),
        };
        let datetime = OffsetDateTime::parse(timestamp, &Rfc3339).map_err(|e| {
            parse_error(format!(
                "ZonedDateTime.parse: cannot parse {timestamp:?} as an RFC 3339 timestamp \
                 (zoneless strings belong to PlainDateTime.parse): {e}"
            ))
        })?;
        let offset_ns = i64::from(datetime.offset().whole_seconds()) * NANOS_PER_SECOND;
        let (offset_value, iana_value) = match iana {
            // An IANA annotation wins over the numeric offset; the offset was
            // still used above to compute the absolute time. The identifier
            // is validated lazily, on first resolution against the host's
            // timezone database.
            Some(iana) => (Value::NULL, Value::object(vm.alloc_string(iana))),
            None => (
                Value::try_int(offset_ns).expect("offset fits in BAML int"),
                Value::NULL,
            ),
        };
        let zoned = copy::time::ZonedDateTime {
            _nanoseconds: Arc::new(num_bigint::BigInt::from(datetime.unix_timestamp_nanos())),
            _offset_ns: offset_value,
            _iana: iana_value,
        };
        Ok(zoned.to_value(vm))
    }
}

impl BamlNamespaceTime for PackageBamlImpl {
    fn _format_zoned(
        epoch_ns: Arc<num_bigint::BigInt>,
        offset_ns: i64,
        iana: Option<&bex_str::BexStr>,
    ) -> Result<bex_str::BexStr, VmRustFnError> {

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Validate/clean offset strings before parsing (offsets within ±23:59).
  2. Report to maintainers if a normal offset string triggers it.
  3. Upgrade the VM build where offset validation covers all parse paths.

Example fix

// before
let z = ZonedDateTime.parse("2024-01-01T00:00:00+99999999:00");
// after
let z = ZonedDateTime.parse("2024-01-01T00:00:00+05:30");
Defensive patterns

Strategy: validation

Validate before calling

// Check the offset portion of a timestamp string is within ±24h before parsing
fn offset_in_range(ts: &str) -> bool {
    ts.rsplit_once(['+', '-']).and_then(|(_, o)| o.split(':').next())
        .and_then(|h| h.parse::<i64>().ok())
        .map(|h| h.abs() <= 24).unwrap_or(true)
}

Try / catch

// Wrap parse in panic boundary when handling untrusted input
std::panic::catch_unwind(|| ZonedDateTime_parse(ts)).unwrap_or_else(|_| Err(ParseError::BadOffset))

Prevention

When it happens

Trigger: Parsing a timezone string with an out-of-range custom offset, or internal state corruption causing an unvalidated offset to reach try_int.

Common situations: Malformed or hostile timestamp strings with absurd offset components (e.g. '+99999999:00') in date/time data being ingested.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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