n8n-io/n8n · error · ExpressionExtensionError

smartJoin(): expected two string args, e.g. .smartJoin("name

Error message

smartJoin(): expected two string args, e.g. .smartJoin("name", "value")

What it means

Thrown as ExpressionExtensionError by the .smartJoin() array extension when its two arguments (keyField, valueField) are missing or not strings. smartJoin builds a single object from an array of objects, using keyField as the key-name source and valueField as the value source for each element. Both must be non-empty strings; otherwise the function cannot know which fields to read.

Source

Thrown at packages/@n8n/expression-runtime/src/extensions/array-extensions.ts:162

function compact(value: unknown[]): unknown[] {
	return value
		.filter((v) => {
			if (v && typeof v === 'object' && Object.keys(v).length === 0) return false;

			return v !== null && v !== undefined && v !== 'nil' && v !== '';
		})
		.map((v) => {
			if (typeof v === 'object' && v !== null) {
				return oCompact(v);
			}
			return v;
		});
}

function smartJoin(value: unknown[], extraArgs: string[]): object {
	const [keyField, valueField] = extraArgs;
	if (!keyField || !valueField || typeof keyField !== 'string' || typeof valueField !== 'string') {
		throw new ExpressionExtensionError(
			'smartJoin(): expected two string args, e.g. .smartJoin("name", "value")',
		);
	}
	// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
	return value.reduce<any>((o, v) => {
		if (typeof v === 'object' && v !== null && keyField in v && valueField in v) {
			// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
			o[(v as any)[keyField]] = (v as any)[valueField];
		}
		// eslint-disable-next-line @typescript-eslint/no-unsafe-return
		return o;
	}, {});
}

function chunk(value: unknown[], extraArgs: number[]) {
	const [chunkSize] = extraArgs;
	if (typeof chunkSize !== 'number' || chunkSize === 0) {
		throw new ExpressionExtensionError('chunk(): expected non-zero numeric arg, e.g. .chunk(5)');

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Pass exactly two string arguments naming the key and value fields: .smartJoin('name', 'value').
  2. Confirm the objects in the array actually contain both fields.
  3. If the field names are dynamic, guard that both are strings before calling.
  4. See the doc example: [{field:'age',value:2},{field:'city',value:'Berlin'}].smartJoin('field','value').

Example fix

// before — missing second argument
{{ $json.rows.smartJoin('field') }}
// after — both field names as strings
{{ $json.rows.smartJoin('field', 'value') }}
Defensive patterns

Strategy: validation

Validate before calling

function smartJoinSafe(arr, keyField, valueField) {
  if (typeof keyField !== 'string' || typeof valueField !== 'string' || !keyField || !valueField) {
    throw new TypeError('smartJoin requires two non-empty string field names');
  }
  // ...proceed
}

Type guard

function areSmartJoinArgsValid(args) {
  return Array.isArray(args) && typeof args[0] === 'string' && typeof args[1] === 'string' && args[0].length > 0 && args[1].length > 0;
}

Try / catch

try {
  result = arr.smartJoin('name', 'value');
} catch (e) {
  if (e.name === 'ExpressionExtensionError' && /smartJoin/i.test(e.message)) {
    // pass exactly two string field names
  }
}

Prevention

When it happens

Trigger: Calling .smartJoin() with zero arguments, one argument, or non-string arguments (e.g. a number or object). Example: [{field:'age',value:2}].smartJoin() (missing second arg) or .smartJoin('field', 42) (second arg not a string).

Common situations: Forgetting the second argument. Passing a variable that resolved to undefined/null instead of a field-name string. Mismatching the field names the objects actually contain.

Related errors


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