fix: provide minimal default settings instead of omitting them

Issue: After fixing the description field removal, integration tests
started failing with "must have required property 'settings'" error.

Root cause: n8n API requires the settings property to be present in
workflow updates, but we were deleting it when no settings were
provided or when all settings were filtered out.

Solution: Instead of deleting settings, provide minimal valid default
settings (executionOrder: 'v0') to satisfy n8n API requirements while
avoiding "additional properties" errors.

This fixes both issues:
- Original #431: Empty settings {} causes "additional properties" error
- New issue: Missing settings causes "required property" error

Updated tests to expect minimal default settings instead of no settings.

Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
czlonkowski
2025-11-20 18:49:36 +01:00
parent a78d7404c0
commit dbd1406c43
2 changed files with 19 additions and 14 deletions

View File

@@ -193,17 +193,18 @@ export function cleanWorkflowForUpdate(workflow: Workflow): Partial<Workflow> {
} }
} }
// Only include settings if it has properties after filtering // n8n API requires settings to be present but rejects empty settings objects.
// n8n API rejects empty settings objects // If no valid properties remain after filtering, include minimal default settings.
if (Object.keys(filteredSettings).length > 0) { if (Object.keys(filteredSettings).length > 0) {
cleanedWorkflow.settings = filteredSettings; cleanedWorkflow.settings = filteredSettings;
} else { } else {
delete cleanedWorkflow.settings; // Provide minimal valid settings (executionOrder is always accepted)
cleanedWorkflow.settings = { executionOrder: 'v0' as const };
} }
} else { } else {
// No settings provided - remove the property entirely // No settings provided - include minimal default settings
// n8n API rejects empty settings objects // n8n API requires settings in workflow updates
delete cleanedWorkflow.settings; cleanedWorkflow.settings = { executionOrder: 'v0' as const };
} }
return cleanedWorkflow; return cleanedWorkflow;

View File

@@ -383,7 +383,7 @@ describe('n8n-validation', () => {
expect(cleaned.name).toBe('Test Workflow'); expect(cleaned.name).toBe('Test Workflow');
}); });
it('should omit settings property when no settings provided (Issue #431)', () => { it('should provide minimal default settings when no settings provided (Issue #431)', () => {
const workflow = { const workflow = {
name: 'Test Workflow', name: 'Test Workflow',
nodes: [], nodes: [],
@@ -391,7 +391,8 @@ describe('n8n-validation', () => {
} as any; } as any;
const cleaned = cleanWorkflowForUpdate(workflow); const cleaned = cleanWorkflowForUpdate(workflow);
expect(cleaned).not.toHaveProperty('settings'); // n8n API requires settings to be present, so we provide minimal defaults
expect(cleaned.settings).toEqual({ executionOrder: 'v0' });
}); });
it('should filter settings to safe properties to prevent API errors (Issue #248 - final fix)', () => { it('should filter settings to safe properties to prevent API errors (Issue #248 - final fix)', () => {
@@ -483,10 +484,11 @@ describe('n8n-validation', () => {
} as any; } as any;
const cleaned = cleanWorkflowForUpdate(workflow); const cleaned = cleanWorkflowForUpdate(workflow);
expect(cleaned).not.toHaveProperty('settings'); // n8n API requires settings, so we provide minimal defaults
expect(cleaned.settings).toEqual({ executionOrder: 'v0' });
}); });
it('should omit settings when only non-whitelisted properties exist (Issue #431)', () => { it('should provide minimal settings when only non-whitelisted properties exist (Issue #431)', () => {
const workflow = { const workflow = {
name: 'Test Workflow', name: 'Test Workflow',
nodes: [], nodes: [],
@@ -499,9 +501,10 @@ describe('n8n-validation', () => {
} as any; } as any;
const cleaned = cleanWorkflowForUpdate(workflow); const cleaned = cleanWorkflowForUpdate(workflow);
// All properties were filtered out, so settings should not exist // All properties were filtered out, but n8n API requires settings
// to avoid "must NOT have additional properties" API error // so we provide minimal defaults to avoid both "additional properties"
expect(cleaned).not.toHaveProperty('settings'); // and "required property" API errors
expect(cleaned.settings).toEqual({ executionOrder: 'v0' });
}); });
it('should preserve whitelisted settings when mixed with non-whitelisted (Issue #431)', () => { it('should preserve whitelisted settings when mixed with non-whitelisted (Issue #431)', () => {
@@ -1403,7 +1406,8 @@ describe('n8n-validation', () => {
expect(forUpdate).not.toHaveProperty('active'); expect(forUpdate).not.toHaveProperty('active');
expect(forUpdate).not.toHaveProperty('tags'); expect(forUpdate).not.toHaveProperty('tags');
expect(forUpdate).not.toHaveProperty('meta'); expect(forUpdate).not.toHaveProperty('meta');
expect(forUpdate).not.toHaveProperty('settings'); // Settings omitted when not present (Issue #431) // n8n API requires settings in updates, so minimal defaults are provided (Issue #431)
expect(forUpdate.settings).toEqual({ executionOrder: 'v0' });
expect(validateWorkflowStructure(forUpdate)).toEqual([]); expect(validateWorkflowStructure(forUpdate)).toEqual([]);
}); });
}); });