vectordotdev/vector · error
invalid timestamp
Error message
invalid timestamp
What it means
table_to_timestamp (lib/vector-core/src/event/lua/util.rs) converts a Lua table with year/month/day/hour/min/sec/nanosec fields into a DateTime<Utc> using chrono's with_ymd_and_hms(...).single().expect("invalid timestamp"). If the components do not form a real instant, single() returns None (ambiguous or non-existent, e.g. Feb 30, month 13, hour 25) or with_nanosecond fails on nano > 999,999,999, and the expect panics inside the Lua/wasmtime host function.
Source
Thrown at lib/vector-core/src/event/lua/util.rs:61
/// This function will fail if the table is malformed.
///
/// # Panics
///
/// Panics if the resulting timestamp is invalid.
#[allow(clippy::needless_pass_by_value)] // constrained by mlua types
pub fn table_to_timestamp(t: LuaTable) -> LuaResult<DateTime<Utc>> {
let year = t.raw_get("year")?;
let month = t.raw_get("month")?;
let day = t.raw_get("day")?;
let hour = t.raw_get("hour")?;
let min = t.raw_get("min")?;
let sec = t.raw_get("sec")?;
let nano = t.raw_get::<Option<u32>>("nanosec")?.unwrap_or(0);
Ok(Utc
.with_ymd_and_hms(year, month, day, hour, min, sec)
.single()
.and_then(|t| t.with_nanosecond(nano))
.expect("invalid timestamp"))
}
View on GitHub (pinned to 3708c39b12)
Solutions
- Clamp and validate components in the Lua script before building the table: 1<=month<=12, day valid for that month/year, hour<=23, min/sec<=59, nanosec<1e9
- Do the date math with a proper library: return epoch seconds/float from Lua and construct the timestamp on the Rust side, or use parse_timestamp in VRL instead of hand-built tables
- Add a Lua-side guard that returns nil / an error string for impossible dates instead of passing them to the host function
Example fix
-- before (lua transform)
local ts = { year = y, month = m, day = d + 1, hour = h, min = mi, sec = s }
-- after: normalize via os.time then rebuild
local tmp = os.date("*t", os.time({ year = y, month = m, day = d, hour = h, min = mi, sec = s }) + 86400)
local ts = { year = tmp.year, month = tmp.month, day = tmp.day, hour = tmp.hour, min = tmp.min, sec = tmp.sec } Defensive patterns
Strategy: validation
Validate before calling
-- Lua-side guard before building the timestamp table
local function valid_ts(t)
return t.month >= 1 and t.month <= 12
and t.day >= 1 and t.day <= 31
and t.hour >= 0 and t.hour <= 23
and t.min >= 0 and t.min <= 59
and t.sec >= 0 and t.sec <= 59
and (t.nanosec or 0) < 1000000000
end
if not valid_ts(ts) then error("invalid timestamp components") end Prevention
- Never roll dates forward by hand in Lua; use os.time/os.date for arithmetic
- Keep sec <= 59 — chrono has no leap-second representation here
- nanosec must be < 1_000_000_000
- Prefer parse_timestamp/format_timestamp VRL functions over hand-built tables
When it happens
Trigger: A Lua transform (or lua VRL-adjacent host call) returning/constructing a timestamp table with out-of-range or impossible values: month=13, day=31 in a 30-day month, hour=24, min=60, sec=61 (no leap second support), or nanosec >= 1_000_000_000. chrono returns None from .single() (or two values would also be None via single) and the expect fires.
Common situations: Lua transform scripts doing date arithmetic by hand (e.g. day = day + 1 rolling past month end), copying 'sec=60' from syslog-style data, parsing timestamps from logs whose fields were never validated, or timezone/DST edge handling done manually in Lua.
Related errors
- invalid timestamp
- not implemented
- Timestamp out of range
- invalid timestamp
- path and query should never fail to parse
AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20).
Data as JSON: /api/errors/41b390482942f1d5.
Report an issue: GitHub.