can1357/oh-my-pi · warning · RangeError
Invalid ISO datetime: ${value}
Error message
Invalid ISO datetime: ${value} What it means
parseIsoDateTimeUtc() builds a Date from the (timezone-normalized) string and throws this RangeError when the result is NaN — meaning the text was non-empty but not a valid ISO 8601 datetime. The original input value is included in the message for diagnosis.
Source
Thrown at packages/mnemopi/src/util/datetime.ts:16
import { recencyHalflifeHours } from "../config";
import { LruCache } from "./lru";
const TZ_RE = /(?:Z|[+-]\d\d:?\d\d)$/;
const DATE_ONLY_RE = /^\d{4}-\d{2}-\d{2}$/;
const TS_CACHE = new LruCache<string, Date>(2000);
export type QueryTime = string | Date | null | undefined;
export function parseIsoDateTimeUtc(value: string): Date {
let text = value.trim();
if (!text) throw new RangeError("Invalid ISO datetime: empty string");
if (DATE_ONLY_RE.test(text)) text += "T00:00:00Z";
else if (!TZ_RE.test(text)) text += "Z";
const date = new Date(text);
if (Number.isNaN(date.getTime())) throw new RangeError(`Invalid ISO datetime: ${value}`);
return date;
}
export function normalizeDateTimeUtc(value: Date): Date {
const time = value.getTime();
if (Number.isNaN(time)) throw new RangeError("Invalid Date");
return new Date(time);
}
export function parseQueryTime(value: QueryTime): Date {
if (value === null || value === undefined) return new Date();
return typeof value === "string" ? parseIsoDateTimeUtc(value) : normalizeDateTimeUtc(value);
}
export function parseTsFast(value: string): Date | undefined {
if (!value) return undefined;
const cached = TS_CACHE.get(value);
if (cached !== undefined) return cached;View on GitHub (pinned to 9690622007)
Solutions
- Send a valid ISO 8601 string: '2026-08-31' or '2026-08-31T14:30:00Z'.
- Convert epoch-millis inputs with new Date(Number(value)) instead of passing them here.
- Pre-validate with a regex/Date.parse check and return a 400-level error to the client before calling.
- Normalize non-ISO formats at the API boundary (e.g. dayjs/Temporal) before parsing.
Example fix
// before
const t = parseQueryTime(req.query.since); // '08/31/2026' -> RangeError
// after
const raw = String(req.query.since ?? '');
const iso = /^\d{4}-\d{2}-\d{2}(T[\d:.]+Z?)?$/.test(raw) ? raw : null;
if (!iso) throw new HttpError(400, 'since must be ISO 8601, e.g. 2026-08-31T00:00:00Z');
const t = parseQueryTime(iso); Defensive patterns
Strategy: validation
Validate before calling
const ISO_RE = /^\d{4}-\d{2}-\d{2}([T ]\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:?\d{2})?)?$/;
function isValidIso(value) {
return typeof value === 'string' && ISO_RE.test(value.trim()) && !Number.isNaN(Date.parse(value));
}
if (!isValidIso(input)) throw new HttpError(400, `since must be ISO 8601, got: ${input}`);
const t = parseQueryTime(input); Type guard
function isIsoDatetimeString(v) {
return typeof v === 'string' && !Number.isNaN(Date.parse(v)) && /^\d{4}-\d{2}-\d{2}/.test(v.trim());
} Try / catch
try {
const t = parseIsoDateTimeUtc(value);
} catch (err) {
if (err instanceof RangeError && err.message.startsWith('Invalid ISO datetime')) {
throw new HttpError(400, `Timestamp must be ISO 8601 (e.g. 2026-08-31T00:00:00Z), got: ${err.message}`);
}
throw err;
} Prevention
- Always send ISO 8601 (YYYY-MM-DD or full RFC 3339 with Z) across APIs
- Convert epoch numbers with new Date(Number(v)), not parseIsoDateTimeUtc
- Pre-validate client-submitted dates and echo the expected format in errors
- Add a form-level date picker instead of free-text date input
When it happens
Trigger: Calling parseIsoDateTimeUtc('not-a-date'), '2026-13-45T99:00:00Z', 'Aug 31 2026', or any non-ISO format (timestamps, locale dates); also via parseQueryTime() with such strings.
Common situations: Free-form user input in time filters, clients sending epoch millis or RFC 2822 dates instead of ISO 8601, copy-pasted dates with locale formatting, or swapped day/month values that overflow.
Related errors
- Invalid ISO datetime: empty string
- Invalid ISO datetime: ${value}
- Invalid Date
- Unknown changelog category: ${raw}
- No JSON payload found in response
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/a4101db1703c976c.
Report an issue: GitHub.