n8n-io/n8n · error · Error
Expression evaluation failed: ${errorMessage}
Error message
Expression evaluation failed: ${errorMessage} What it means
Thrown as a generic Error('Expression evaluation failed: <errorMessage>') by IsolatedVmBridge.execute() when the isolate raised an error that is NOT an ExpressionError/ExpressionExtensionError, NOT a timeout, and NOT a memory-limit hit. It is the catch-all wrapper for everything else: unexpected runtime exceptions, uncaught TypeErrors from host callbacks (intentionally not special-cased), syntax issues that slipped past tournament, or isolate-internal failures. The original message is appended for diagnostics.
Source
Thrown at packages/@n8n/expression-runtime/src/bridge/isolated-vm-bridge.ts:798
// so TypeErrors from host callbacks should also go through the generic
// wrapping for consistent behavior.
if (
error instanceof Error &&
(error.name === 'ExpressionError' || error.name === 'ExpressionExtensionError')
) {
throw error;
}
const errorMessage = error instanceof Error ? error.message : String(error);
if (errorMessage.includes('Script execution timed out')) {
throw new TimeoutError(`Expression timed out after ${this.config.timeout}ms`, {});
}
if (errorMessage.includes('memory limit')) {
throw new MemoryLimitError(
`Expression exceeded memory limit of ${this.config.memoryLimit}MB`,
{},
);
}
throw new Error(`Expression evaluation failed: ${errorMessage}`);
} finally {
getValueAtPath.release();
getArrayElement.release();
callHost.release();
}
}
/**
* Reconstruct an error from serialized isolate data.
*
* Maps error names back to their host-side classes and restores
* custom properties that would otherwise be lost crossing the boundary.
*/
private reconstructError(data: ErrorSentinel): Error {
const error = new Error(data.message);
error.name = data.name || 'Error';
if (data.stack) {
error.stack = data.stack;View on GitHub (pinned to 5ac6606e81)
Solutions
- Read the appended errorMessage — it is the isolate's original error text and usually pinpoints the cause.
- Reproduce the expression in isolation to see the underlying error class.
- If a host callback is the source, ensure it throws ExpressionError/ExpressionExtensionError so it is re-thrown verbatim instead of wrapped.
- Simplify the expression to the smallest reproducer to isolate the failing operation.
- Check for undefined/null access on $json fields that the expression assumes exist.
Example fix
// before — expression assumes a field exists; underlying ReferenceError gets wrapped
const result = evaluator.evaluate('{{ $json.contact.email.toUpperCase() }}', data, caller);
// after — guard access; if it still fails, inspect the wrapped message
try {
const result = evaluator.evaluate('{{ $json.contact?.email?.toUpperCase() }}', data, caller);
} catch (e) {
// e.message === 'Expression evaluation failed: Cannot read properties of undefined ...'
console.error(e.message);
} Defensive patterns
Strategy: try-catch
Validate before calling
// No general pre-check covers all causes; narrow with targeted guards, e.g. null-safe access
function toNullSafe(expr) { return expr.replace(/\.(\w+)/g, '?.$1'); } // conservative optional-chaining hint Type guard
function isExpressionEvaluationFailure(e) {
return e instanceof Error && e.message.startsWith('Expression evaluation failed:');
} Try / catch
try {
const result = evaluator.evaluate(expr, data, caller);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Expression evaluation failed:')) {
// the appended text after the colon is the isolate's original error message
console.error('Underlying isolate error:', e.message.slice('Expression evaluation failed:'.length).trim());
} else throw e;
} Prevention
- Use optional chaining (?.) in expressions to avoid Cannot-read-of-undefined errors.
- If you build host callbacks, throw ExpressionError/ExpressionExtensionError so they are re-thrown verbatim instead of wrapped.
- Reproduce the failing expression in isolation to read the underlying error class.
- Simplify the expression to a minimal reproducer to locate the failing operation.
When it happens
Trigger: Any isolate execution failure that doesn't match the timeout/memory/ExpressionError branches: a host callback throwing a non-Expression error, a ReferenceError inside the expression, a tournament-transformed code bug, or an isolate-internal fault. The wrapped errorMessage is the isolate's original text.
Common situations: A user expression referencing an undefined variable/method. A host callback (getValueAtPath/getArrayElement/callHost) throwing a non-Expression error due to unexpected data shape. A version skew between tournament transforms and the bridge. Debugging an expression that fails in an unclassified way.
Related errors
- Expression timed out after ${this.config.timeout}ms
- Expression exceeded memory limit of ${this.config.memoryLimi
- Isolate for this caller is no longer available
- Request to Azure Blob storage failed: ${error.message}
- Request to S3 failed: ${error.message}
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/0b7b127cad3ccada.
Report an issue: GitHub.