can1357/oh-my-pi · error · RangeError

Invalid Date

Error message

Invalid Date

What it means

normalizeDateUtc validates that a Date object holds a real, finite timestamp before re-wrapping it. JavaScript allows constructing Dates that hold NaN (e.g. `new Date("garbage")` or `new Date(NaN)`), and this library refuses to propagate such values into scoring/recall math, throwing a RangeError instead of silently producing NaN scores.

Source

Thrown at packages/mnemopi/src/core/beam/helpers.ts:120

): HybridWeights {
	let vw = Math.max(0, vecWeight ?? envNumber("MNEMOPI_VEC_WEIGHT", DEFAULT_WEIGHTS[0]));
	let fw = Math.max(0, ftsWeight ?? envNumber("MNEMOPI_FTS_WEIGHT", DEFAULT_WEIGHTS[1]));
	let iw = Math.max(0, importanceWeight ?? envNumber("MNEMOPI_IMPORTANCE_WEIGHT", DEFAULT_WEIGHTS[2]));
	if (!Number.isFinite(vw)) vw = 0;
	if (!Number.isFinite(fw)) fw = 0;
	if (!Number.isFinite(iw)) iw = 0;
	const total = vw + fw + iw;
	if (total === 0) return DEFAULT_WEIGHTS;
	return [vw / total, fw / total, iw / total];
}

export function normalizeImportance(importance: number | null | undefined, fallback = 0.5): number {
	return clamp01(importance ?? fallback);
}

export function normalizeDateUtc(dt: Date): Date {
	const time = dt.getTime();
	if (!Number.isFinite(time)) throw new RangeError("Invalid Date");
	return new Date(time);
}

export function parseIsoDateTimeUtc(value: string): Date {
	const normalized = value.endsWith("Z") ? value : value.replace(/Z$/, "+00:00");
	const dt = new Date(normalized);
	if (!Number.isFinite(dt.getTime())) throw new RangeError(`Invalid ISO datetime: ${value}`);
	return dt;
}

export function parseQueryTime(queryTime?: string | Date | null): Date {
	if (queryTime == null) return new Date();
	if (queryTime instanceof Date) return normalizeDateUtc(queryTime);
	try {
		return parseIsoDateTimeUtc(queryTime);
	} catch {
		return parseIsoDateTimeUtc(`${queryTime}T00:00:00`);
	}

View on GitHub (pinned to 9690622007)

Solutions

  1. Validate the Date before passing it: check `Number.isFinite(date.getTime())`.
  2. If constructing from a string, use parseIsoDateTimeUtc or parseQueryTime with a proper ISO-8601 string (optionally with Z or offset).
  3. If the Date came from user input, surface a validation message instead of constructing an invalid Date.

Example fix

// before
const queryTime = new Date(userInput); // userInput = "next tuesday-ish"
recall(query, { queryTime });
// after
const queryTime = new Date(userInput);
if (Number.isNaN(queryTime.getTime())) throw new Error(`Unparseable date: ${userInput}`);
recall(query, { queryTime });
Defensive patterns

Strategy: validation

Validate before calling

function isValidDate(d: unknown): d is Date {
  return d instanceof Date && Number.isFinite(d.getTime());
}
// before calling: if (!isValidDate(queryTime)) throw new Error("bad queryTime");

Type guard

function isValidDate(d: unknown): d is Date {
  return d instanceof Date && Number.isFinite(d.getTime());
}

Try / catch

try {
  const qt = normalizeDateUtc(candidate);
} catch (e) {
  if (e instanceof RangeError && e.message === "Invalid Date") {
    // fall back to new Date()
  } else throw e;
}

Prevention

When it happens

Trigger: Calling an API that accepts `queryTime` (via parseQueryTime) with a Date instance created from an unparseable string, NaN, or an out-of-range numeric value, so `dt.getTime()` returns NaN and `Number.isFinite` fails.

Common situations: Passing a Date parsed from user-supplied free-text input, deserializing a JSON value like `"undefined"` into a Date, or doing date arithmetic that overflows (e.g. adding Infinity hours).

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/db8bdb34008f51fe. Report an issue: GitHub.