n8n-io/n8n · error · ExpressionExtensionError
Unsupported format '${String(valueFormat)}'. toDateTime() su
Error message
Unsupported format '${String(valueFormat)}'. toDateTime() supports 'ms', 's', 'us' and 'excel'. What it means
The NUMBER variant of `.toDateTime(format)` accepts only `'ms'`, `'s'`, `'us'`, and `'excel'` (milliseconds, seconds, microseconds, and days-since-1900 respectively). Any other format string throws; the four valid tokens are listed in the message. (The STRING variant of `.toDateTime()` is a different function and accepts Luxon format tokens.)
Source
Thrown at packages/@n8n/expression-runtime/src/extensions/number-extensions.ts:75
function toBoolean(value: number) {
return value !== 0;
}
function toInt(value: number) {
return round(value, []);
}
function toFloat(value: number) {
return value;
}
type DateTimeFormat = 'ms' | 's' | 'us' | 'excel';
export function toDateTime(value: number, extraArgs: [DateTimeFormat]) {
const [valueFormat = 'ms'] = extraArgs;
if (!['ms', 's', 'us', 'excel'].includes(valueFormat)) {
throw new ExpressionExtensionError(
`Unsupported format '${String(valueFormat)}'. toDateTime() supports 'ms', 's', 'us' and 'excel'.`,
);
}
switch (valueFormat) {
// Excel format is days since 1900
// There is a bug where 1900 is incorrectly treated as a leap year
case 'excel': {
const DAYS_BETWEEN_1900_1970 = 25567;
const DAYS_LEAP_YEAR_BUG_ADJUST = 2;
const SECONDS_IN_DAY = 86_400;
return DateTime.fromSeconds(
(value - (DAYS_BETWEEN_1900_1970 + DAYS_LEAP_YEAR_BUG_ADJUST)) * SECONDS_IN_DAY,
);
}
case 's':
return DateTime.fromSeconds(value);
case 'us':View on GitHub (pinned to 5ac6606e81)
Solutions
- Use one of `ms`, `s`, `us`, `excel` for numeric inputs.
- If the source is an ISO/date string, use the string `.toDateTime()` variant (or `.toDate()`) instead.
- Convert exotic epochs in a Code node (e.g. nanoseconds → milliseconds) before calling `.toDateTime('ms')`.
Example fix
// before
{{ $json.epochMicros.toDateTime('micros') }}
// after
{{ $json.epochMicros.toDateTime('us') }} Defensive patterns
Strategy: validation
Validate before calling
const FORMATS = new Set(['ms','s','us','excel']);
const fmt = $json.fmt;
if (typeof $json.value === 'number' && !FORMATS.has(fmt)) {
throw new Error(`toDateTime(): unsupported numeric format '${fmt}'`);
}
return $json; Type guard
const isNumericDateTimeFormat = (f: string): f is 'ms'|'s'|'us'|'excel' => ['ms','s','us','excel'].includes(f);
Prevention
- For numeric epochs use only ms/s/us/excel.
- For ISO/date strings use the string `.toDateTime()` variant instead.
- Convert exotic epochs (e.g. nanos) to milliseconds in a Code node first.
When it happens
Trigger: Calling `.toDateTime('nanos')`, `.toDateTime('iso')`, or passing a Luxon token like `'yyyy'` on a numeric value.
Common situations: Copy-pasting a format token from the string variant; assuming arbitrary units are supported; passing a unit the source system uses but n8n does not.
Related errors
- Unsupported unit '${String(errorUnit)}'. Supported: ${durati
- cannot convert to Luxon DateTime
- Invalid model ID "${rawId}": expected "provider/model-name"
- intersection(): expected array arg, e.g. .intersection([1, 2
- isBetween(): expected exactly two args
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/f8d5963d41e4a4cb.
Report an issue: GitHub.