napi-rs/napi-rs · error · DateExpected
Found invalid date
Error message
Found invalid date
What it means
Thrown when converting a JS Date to `DateTime<Local>`: `napi_get_date_value` returns milliseconds since epoch, and `Local.timestamp_millis_opt` fails to produce a unique/valid local datetime (LocalResult::None or Ambiguous). The library raises Status::DateExpected with this message instead of returning a DateTime.
Solutions
- Validate the Date on the JS side before calling: check `!Number.isNaN(date.getTime())`.
- Verify the epoch milliseconds do not fall into a DST gap for the machine's local timezone, or use a UTC-based type (`DateTime<Utc>` vs `NaiveDateTime`) on the Rust side.
- Set the process/container TZ to a known zone (e.g. TZ=UTC) if DST ambiguity is the cause.
- Inspect the incoming Date with `date.toISOString()` in JS to confirm it represents a real instant.
Example fix
// before
fn schedule(dt: DateTime<Local>) { ... }
schedule(new Date(undefined));
// after (JS side guard)
const d = new Date(input);
if (Number.isNaN(d.getTime())) throw new Error('invalid date');
schedule(d); Defensive patterns
Strategy: validation
Validate before calling
function assertValidDate(d) {
if (!(d instanceof Date) || Number.isNaN(d.getTime())) {
throw new TypeError('Expected a valid Date, got: ' + String(d));
}
} Type guard
function isValidDate(v) { return v instanceof Date && !Number.isNaN(v.getTime()); } Try / catch
try { mod.schedule(d); } catch (e) { if (String(e.message).includes('Found invalid date')) { console.error('Date invalid or falls in DST gap'); } else throw e; } Prevention
- Always validate Date values with Number.isNaN(d.getTime()) before native calls.
- Avoid constructing dates inside DST gap hours from local components (new Date(2024,2,10,2,30) in affected zones).
- Prefer UTC-based timestamps (epoch millis) when crossing timezone boundaries.
- Pin TZ (e.g. TZ=UTC) in CI and containers for deterministic behavior.
When it happens
Trigger: Calling a #[napi] function with a `DateTime<Local>` (or `DateTime<Utc>` mapped through this impl) parameter when the epoch milliseconds map to a nonexistent or ambiguous local time, or the JS value is an invalid Date (NaN time, e.g. `new Date(NaN)`).
Common situations: DST transitions where `new Date(...)` epoch value maps into a skipped/ambiguous local hour in the user's timezone; passing `new Date(undefined)` or `Invalid Date` from JS.
Related errors
AI-assisted analysis of napi-rs/napi-rs@39bd1205e4 (2026-09-13).
Data as JSON: /api/errors/1be4717fd5be21e9.
Report an issue: GitHub.
Appendix: source
Thrown at crates/napi/src/bindgen_runtime/js_values/date.rs:148
Ok(ptr)
}
}
impl<Tz: TimeZone> FromNapiValue for DateTime<Tz>
where
DateTime<Tz>: From<DateTime<Local>>,
{
unsafe fn from_napi_value(env: sys::napi_env, napi_val: sys::napi_value) -> Result<Self> {
let mut milliseconds_since_epoch_utc = 0.0;
check_status!(
unsafe { sys::napi_get_date_value(env, napi_val, &mut milliseconds_since_epoch_utc) },
"Failed to convert napi value into rust type `DateTime`",
)?;
match Local.timestamp_millis_opt(milliseconds_since_epoch_utc as i64) {
LocalResult::Single(dt) => Ok(dt.into()),
_ => Err(Error::new(
Status::DateExpected,
"Found invalid date".to_owned(),
)),
}
}
}
View on GitHub (pinned to 39bd1205e4)