n8n-io/n8n · error · ExpressionExtensionError

cannot convert to Luxon DateTime

Error message

cannot convert to Luxon DateTime

What it means

A catch-all wrapper around the STRING `.toDateTime()` body. The outer `try`/`catch` re-throws any inner failure (unknown format string that is not `ms`/`s`/`us`/`excel` and not a valid Luxon token, an unparseable value with a custom format, or a throw from the number-conversion path) as the generic 'cannot convert to Luxon DateTime'. It obscures the underlying cause.

Source

Thrown at packages/@n8n/expression-runtime/src/extensions/string-extensions.ts:211

export function toDateTime(value: string, extraArgs: [string] = ['']): DateTime {
	try {
		const [valueFormat] = extraArgs;

		if (valueFormat) {
			if (
				valueFormat === 'ms' ||
				valueFormat === 's' ||
				valueFormat === 'us' ||
				valueFormat === 'excel'
			) {
				return numberToDateTime(Number(value), [valueFormat]);
			}
			return DateTime.fromFormat(value, valueFormat);
		}

		return tryToParseDateTime(value);
	} catch (error) {
		throw new ExpressionExtensionError('cannot convert to Luxon DateTime');
	}
}

function urlDecode(value: string, extraArgs: boolean[]): string {
	const [entireString = false] = extraArgs;
	if (entireString) {
		return decodeURI(value.toString());
	}
	return decodeURIComponent(value.toString());
}

function urlEncode(value: string, extraArgs: boolean[]): string {
	const [entireString = false] = extraArgs;
	if (entireString) {
		return encodeURI(value.toString());
	}
	return encodeURIComponent(value.toString());
}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Omit the format argument to use auto-detection, OR supply a valid Luxon format token (e.g. `'yyyy-MM-dd HH:mm:ss'`).
  2. If the value is numeric, use the number `.toDateTime('ms'|'s'|'us'|'excel')` variant instead.
  3. Pre-parse in a Code node with Luxon `DateTime.fromFormat` to surface the real error, then forward the DateTime.

Example fix

// before
{{ $json.stamp.toDateTime('YYYY-mm-dd') }}
// after
{{ $json.stamp.toDateTime('yyyy-MM-dd') }}
Defensive patterns

Strategy: try-catch

Validate before calling

// Validate format token + parseability before the expression:
const luxon = require('luxon');
const dt = luxon.DateTime.fromFormat($json.stamp, $json.fmt || '');
if (!dt.isValid) {
  throw new Error(`cannot convert to Luxon DateTime: ${dt.invalidReason}`);
}
return $json;

Type guard

const isValidLuxonDateTime = (dt: { isValid: boolean }): boolean => dt.isValid;

Try / catch

try {
  return $json.stamp.toDateTime($json.fmt).toISO();
} catch {
  // fall back to auto-detection or a quarantine branch
  return $json.stamp.toDateTime().toISO();
}

Prevention

When it happens

Trigger: Passing a format argument that is neither a numeric shortcut nor a valid Luxon format token (e.g. `.toDateTime('YYYY')` with wrong casing, or `.toDateTime('iso8601')`); or a value that cannot be parsed with the supplied format.

Common situations: Custom format string Luxon rejects; downstream of 335/337 when a format was supplied; year-first vs day-first locale confusion.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/92d233f1ab238a8d. Report an issue: GitHub.