fix: Handle null and undefined in manual console output (#41570)

Co-authored-by: n8n-cat-bot[bot] <n8n-cat-bot[bot]@users.noreply.github.com>
This commit is contained in:
n8n-cat-bot[bot] 2026-10-21 11:45:17 +00:00 committed by GitHub
parent f15b08b42f
commit e228ee968e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 0 deletions

View File

@ -254,6 +254,46 @@ describe('ExecuteContext', () => {
});
describe('logNodeOutput', () => {
// NODE-5746: Forward valid Code node logs to the editor without server warnings.
it.each([
{ logCall: 'console.log("x", 42)', args: ['x', 42], messages: ['x', 42] },
{ logCall: 'console.log(null)', args: [null], messages: ['null'] },
{ logCall: 'console.log(undefined)', args: [undefined], messages: ['undefined'] },
{ logCall: 'console.log("x", null)', args: ['x', null], messages: ['x', 'null'] },
])(
'should forward $logCall to the editor in manual mode without warnings',
({ args, messages }) => {
const sendDataToUI = vi.fn();
const codeNode = mock<INode>({
name: 'Code',
type: 'n8n-nodes-base.code',
typeVersion: 2,
});
const context = new ExecuteContext(
mock<Workflow>({ settings: { redactionPolicy: 'none' } }),
codeNode,
mock<IWorkflowExecuteAdditionalData>({ sendDataToUI }),
'manual',
mock<IRunExecutionData>(),
runIndex,
connectionInputData,
inputData,
executeData,
[],
);
const warnSpy = vi.spyOn(context.logger, 'warn').mockImplementation(() => {});
context.logNodeOutput(...args);
expect.soft(warnSpy).not.toHaveBeenCalled();
expect(sendDataToUI).toHaveBeenCalledTimes(1);
expect(sendDataToUI).toHaveBeenCalledWith('sendConsoleMessage', {
source: '[Node: "Code"]',
messages,
});
},
);
it('when in manual mode, should parse JSON', () => {
const json = '{"key": "value", "nested": {"foo": "bar"}}';
const expectedParsedObject = { key: 'value', nested: { foo: 'bar' } };

View File

@ -425,6 +425,8 @@ export class BaseExecuteContext extends NodeExecutionContext {
try {
if (this.additionalData.sendDataToUI) {
args = args.map((arg) => {
if (arg === null || arg === undefined) return String(arg);
// prevent invalid dates from being logged as null
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-return
if (arg.isLuxonDateTime && arg.invalidReason) return { ...arg };