Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 22 additions & 15 deletions nodes/VlmRun/VlmRun.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
INodePropertyOptions,
INodeTypeDescription,
} from 'n8n-workflow';

import { FileRequest, ChatMessage, ResponseFormat } from './types';
import { ApiService } from './ApiService';
import { processFile, processImageRequest } from './utils';
Expand Down Expand Up @@ -68,25 +69,25 @@ export class VlmRun implements INodeType {
description: 'Extract insights or transcribe content from video files',
action: 'Analyze video',
},
{
name: 'Chat Completion',
value: 'chatCompletion',
description: 'Generate chat completions using OpenAI-compatible API',
action: 'Chat completion',
},
{
name: 'Execute Agent',
value: 'executeAgent',
description: 'Execute an agent',
action: 'Execute agent',
},
{
name: 'Manage Files',
value: 'file',
description: 'List uploaded files or upload new files to VLM Run',
action: 'Manage files',
},
{
name: 'Chat Completion',
value: 'chatCompletion',
description: 'Generate chat completions using OpenAI-compatible API',
action: 'Chat completion',
},
],
{
name: 'Manage Files',
value: 'file',
description: 'List uploaded files or upload new files to VLM Run',
action: 'Manage files',
},
],
default: 'document',
},
// File field for document, image, audio, video operations
Expand Down Expand Up @@ -893,7 +894,10 @@ export class VlmRun implements INodeType {

// Validate that if type is json_schema, schema must be provided
if (userDefinedResponseFormat.type === 'json_schema' && !userDefinedResponseFormat.schema) {
throw new Error('Schema is required when type is "json_schema"');
throw new NodeOperationError(
this.getNode(),
'Schema is required when type is "json_schema"',
);
Comment on lines +897 to +900
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While replacing Error with NodeOperationError is a good step for consistency, placing this validation logic inside the try...catch block (lines 866-921) leads to a confusing experience for the user. This catch block is designed for JSON parsing errors, but it will also catch this validation error and wrap it with the misleading message Invalid JSON format for response_format.... At this stage, the JSON is structurally valid, but semantically incorrect.

This issue also affects the validation on lines 911-914.

To provide clearer error messages, I recommend moving all semantic validation logic outside the try...catch block, which should only be responsible for parsing the JSON string.

Here's a suggested structure:

let parsed: any;
try {
    // ... parsing logic for responseFormatParam
} catch (error) {
    throw new NodeOperationError(
        this.getNode(),
        `Invalid JSON format for response_format: ${error instanceof Error ? error.message : String(error)}`
    );
}

// Perform semantic validation on the 'parsed' object here
if (parsed && typeof parsed === 'object') {
    // ...
    if (userDefinedResponseFormat.type === 'json_schema' && !userDefinedResponseFormat.schema) {
        throw new NodeOperationError(
            this.getNode(),
            'Schema is required when type is "json_schema"',
        );
    }
    // ...
} else if (parsed !== undefined) {
    throw new NodeOperationError(
        this.getNode(),
        'Response format must be an object',
    );
}

}

// For structured outputs (json_schema), ensure strict is set to true if not provided
Expand All @@ -904,7 +908,10 @@ export class VlmRun implements INodeType {
}
// If it's an empty object or doesn't have type/schema, treat as undefined (ignore it)
} else if (parsed !== undefined) {
throw new Error('Response format must be an object');
throw new NodeOperationError(
this.getNode(),
'Response format must be an object',
);
}
} catch (error) {
throw new NodeOperationError(
Expand Down