denoland/deno · error · InvalidData
invalid , must not be infinity or NaN
Error message
invalid ${name}, must not be infinity or NaN What it means
fs.lutimes(path, atime, mtime, callback) converts each TimeLike (Date, number, or numeric string) into unix seconds/nanoseconds via getValidUnixTime. Strings are coerced with Number(), and if the resulting value is NaN or Infinity the polyfill throws Deno.errors.InvalidData with 'invalid atime/mtime, must not be infinity or NaN'. This guards the OS-level utimensat call, which cannot accept non-finite timestamps.
Solutions
- Validate before calling: Number.isFinite(new Date(atime).getTime())
- Sanitize strings with a fallback: Number.isNaN(Number(s)) ? Date.now() : s
- If the value may be absent, pass a fresh Date or omit the lutimes call instead of sending NaN
Example fix
// before
fs.lutimes(path, 'yesterday-ish', mtime, cb); // Number('yesterday-ish') = NaN
// after
const atime = new Date('2024-01-01T00:00:00Z');
if (Number.isFinite(atime.getTime())) {
fs.lutimes(path, atime.getTime() / 1000, mtime, cb);
} Defensive patterns
Strategy: validation
Validate before calling
const toTime = (v) => typeof v === 'string' ? Number(v) : (v instanceof Date ? v.getTime() / 1000 : v);
if (!Number.isFinite(toTime(atime)) || !Number.isFinite(toTime(mtime))) throw new RangeError('atime/mtime must be finite'); Type guard
const isValidTimeLike = (v) => { const n = typeof v === 'string' ? Number(v) : (v instanceof Date ? v.getTime() / 1000 : v); return typeof n === 'number' && Number.isFinite(n); }; Try / catch
try { fs.lutimesSync(p, atime, mtime); } catch (e) { if (e instanceof Deno.errors.InvalidData) { /* coerce to a sane default and retry once with Date.now() */ } else throw e; } Prevention
- Never pass unvalidated user strings as timestamps
- Check Number.isFinite(Date.parse-like values) before utimes-family calls
- Invalid Date objects (new Date(badString)) have NaN getTime() — validate the Date itself
When it happens
Trigger: fs.lutimes(path, 'not-a-date', new Date(), cb) — Number('not-a-date') is NaN; passing an already-invalid Date (new Date('garbage')) whose getTime() is NaN; passing Infinity from a computation like 1/0 or Number.MAX_VALUE * 2; an empty string atime ('' coerces to 0 and passes, but 'abc' fails).
Common situations: Parsing timestamps from filenames or metadata that may not be numeric; feeding client-supplied strings straight into utimes-style APIs; DST/parse edge cases producing Invalid Date objects.
Related errors
AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20).
Data as JSON: /api/errors/700e3601693045b6.
Report an issue: GitHub.
Appendix: source
Thrown at ext/node/polyfills/_fs/_fs_lutimes.ts:37
PromisePrototypeThen,
} = primordials;
type TimeLike = number | string | Date;
type PathLike = string | Buffer | URL;
function getValidUnixTime(
value: TimeLike,
name: string,
): [number, number] {
if (typeof value === "string") {
value = Number(value);
}
if (
typeof value === "number" &&
(NumberIsNaN(value) || !NumberIsFinite(value))
) {
throw new Deno.errors.InvalidData(
`invalid ${name}, must not be infinity or NaN`,
);
}
const unixSeconds = toUnixTimestamp(value);
const seconds = MathTrunc(unixSeconds);
const nanoseconds = MathTrunc((unixSeconds * 1e3) - (seconds * 1e3)) * 1e6;
return [
seconds,
nanoseconds,
];
}
export function lutimes(
path: PathLike,
atime: TimeLike,View on GitHub (pinned to 9ad36f7a2c)