BoundaryML/baml · error

PlainDateTime.to_plain_date: expected PlainDateTime instance

Error message

PlainDateTime.to_plain_date: expected PlainDateTime instance

What it means

Panic in PlainDateTime.to_plain_date: the receiver value is not a PlainDateTime instance, so reading its nanoseconds field fails. The method assumes its receiver is always a proper PlainDateTime instance.

Solutions

  1. Confirm the receiver was built with PlainDateTime constructors before calling to_plain_date.
  2. If the value is a PlainDate, it already is a date — no conversion needed.
  3. Type-check the value before the call.

Example fix

// before
let d = plaindate.to_plain_date()
// after
let d = plaindatetime.to_plain_date()  // receiver must be PlainDateTime
Defensive patterns

Strategy: type-guard

Validate before calling

// before the call
if (typeof value.className !== 'undefined' && value.className !== 'PlainDateTime') throw new Error('receiver must be a PlainDateTime');

Type guard

function isPlainDateTime(v) { return v != null && v.className === 'PlainDateTime'; }

Prevention

When it happens

Trigger: Calling to_plain_date with a receiver that is a PlainDate, PlainTime, or other non-PlainDateTime value.

Common situations: Confusing PlainDate with PlainDateTime when chaining conversions; retrieving dates from dynamic/untyped data; wrong-variable mistakes.

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-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/b9b484cf585c0c8a. Report an issue: GitHub.

Appendix: source

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

        let dt = civil_datetime(&plaindatetime._nanoseconds(), "PlainDateTime.to_string")?;
        let mut out = String::new();
        format_date_into(&mut out, dt.date());
        out.push('T');
        format_clock_into(
            &mut out,
            dt.hour(),
            dt.minute(),
            dt.second(),
            dt.nanosecond(),
        );
        Ok(bex_str::BexStr::from(out))
    }

    fn to_plain_date(vm: &mut BexVm, plaindatetime: &Value) -> Result<Value, VmRustFnError> {
        let civil = {
            let instance = vm
                .as_instance(plaindatetime)
                .expect("PlainDateTime.to_plain_date: expected PlainDateTime instance");
            view::time::PlainDateTime { instance }._nanoseconds()
        };
        let days = i128::try_from(&*civil)
            .ok()
            .map(|n| n.div_euclid(NANOS_PER_DAY))
            .and_then(|d| i64::try_from(d).ok())
            .ok_or_else(|| {
                invalid_argument(
                    "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

View on GitHub (pinned to bd85ce9dee)