Files
gh-czlonkowski-n8n-skills/skills/n8n-node-configuration/DEPENDENCIES.md
2025-11-29 18:17:17 +08:00

14 KiB

Property Dependencies Guide

Deep dive into n8n property dependencies and displayOptions mechanism.


What Are Property Dependencies?

Definition: Rules that control when fields are visible or required based on other field values.

Mechanism: displayOptions in node schema

Purpose:

  • Show relevant fields only
  • Hide irrelevant fields
  • Simplify configuration UX
  • Prevent invalid configurations

displayOptions Structure

Basic Format

{
  "name": "fieldName",
  "type": "string",
  "displayOptions": {
    "show": {
      "otherField": ["value1", "value2"]
    }
  }
}

Translation: Show fieldName when otherField equals "value1" OR "value2"

Show vs Hide

show (Most Common)

Show field when condition matches:

{
  "name": "body",
  "displayOptions": {
    "show": {
      "sendBody": [true]
    }
  }
}

Meaning: Show body when sendBody = true

hide (Less Common)

Hide field when condition matches:

{
  "name": "advanced",
  "displayOptions": {
    "hide": {
      "simpleMode": [true]
    }
  }
}

Meaning: Hide advanced when simpleMode = true

Multiple Conditions (AND Logic)

{
  "name": "body",
  "displayOptions": {
    "show": {
      "sendBody": [true],
      "method": ["POST", "PUT", "PATCH"]
    }
  }
}

Meaning: Show body when:

  • sendBody = true AND
  • method IN (POST, PUT, PATCH)

All conditions must match (AND logic)

Multiple Values (OR Logic)

{
  "name": "someField",
  "displayOptions": {
    "show": {
      "method": ["POST", "PUT", "PATCH"]
    }
  }
}

Meaning: Show someField when:

  • method = POST OR
  • method = PUT OR
  • method = PATCH

Any value matches (OR logic)


Common Dependency Patterns

Pattern 1: Boolean Toggle

Use case: Optional feature flag

Example: HTTP Request sendBody

// Field: sendBody (boolean)
{
  "name": "sendBody",
  "type": "boolean",
  "default": false
}

// Field: body (depends on sendBody)
{
  "name": "body",
  "displayOptions": {
    "show": {
      "sendBody": [true]
    }
  }
}

Flow:

  1. User sees sendBody checkbox
  2. When checked → body field appears
  3. When unchecked → body field hides

Pattern 2: Resource/Operation Cascade

Use case: Different operations show different fields

Example: Slack message operations

// Operation: post
{
  "name": "channel",
  "displayOptions": {
    "show": {
      "resource": ["message"],
      "operation": ["post"]
    }
  }
}

// Operation: update
{
  "name": "messageId",
  "displayOptions": {
    "show": {
      "resource": ["message"],
      "operation": ["update"]
    }
  }
}

Flow:

  1. User selects resource="message"
  2. User selects operation="post" → sees channel
  3. User changes to operation="update" → channel hides, messageId shows

Pattern 3: Type-Specific Configuration

Use case: Different types need different fields

Example: IF node conditions

// String operations
{
  "name": "value2",
  "displayOptions": {
    "show": {
      "conditions.string.0.operation": ["equals", "notEquals", "contains"]
    }
  }
}

// Unary operations (isEmpty) don't show value2
{
  "displayOptions": {
    "hide": {
      "conditions.string.0.operation": ["isEmpty", "isNotEmpty"]
    }
  }
}

Pattern 4: Method-Specific Fields

Use case: HTTP methods have different options

Example: HTTP Request

// Query parameters (all methods can have)
{
  "name": "queryParameters",
  "displayOptions": {
    "show": {
      "sendQuery": [true]
    }
  }
}

// Body (only certain methods)
{
  "name": "body",
  "displayOptions": {
    "show": {
      "sendBody": [true],
      "method": ["POST", "PUT", "PATCH", "DELETE"]
    }
  }
}

Using get_property_dependencies

Basic Usage

const deps = get_property_dependencies({
  nodeType: "nodes-base.httpRequest"
});

Example Response

{
  "nodeType": "n8n-nodes-base.httpRequest",
  "dependencies": {
    "body": {
      "shows_when": {
        "sendBody": [true],
        "method": ["POST", "PUT", "PATCH", "DELETE"]
      },
      "required_when_shown": true
    },
    "queryParameters": {
      "shows_when": {
        "sendQuery": [true]
      },
      "required_when_shown": false
    },
    "headerParameters": {
      "shows_when": {
        "sendHeaders": [true]
      },
      "required_when_shown": false
    }
  }
}

When to Use

Use when:

  • Validation fails with "missing field" but you don't see that field
  • A field appears/disappears unexpectedly
  • You need to understand what controls field visibility
  • Building dynamic configuration tools

Don't use when:

  • Simple configuration (use get_node_essentials)
  • Just starting configuration
  • Field requirements are obvious

Complex Dependency Examples

Example 1: HTTP Request Complete Flow

Scenario: Configuring POST with JSON body

Step 1: Set method

{
  "method": "POST"
  // → sendBody becomes visible
}

Step 2: Enable body

{
  "method": "POST",
  "sendBody": true
  // → body field becomes visible AND required
}

Step 3: Configure body

{
  "method": "POST",
  "sendBody": true,
  "body": {
    "contentType": "json"
    // → content field becomes visible AND required
  }
}

Step 4: Add content

{
  "method": "POST",
  "sendBody": true,
  "body": {
    "contentType": "json",
    "content": {
      "name": "John",
      "email": "john@example.com"
    }
  }
}
// ✅ Valid!

Dependency chain:

method=POST
  → sendBody visible
    → sendBody=true
      → body visible + required
        → body.contentType=json
          → body.content visible + required

Example 2: IF Node Operator Dependencies

Scenario: String comparison with different operators

Binary operator (equals):

{
  "conditions": {
    "string": [
      {
        "operation": "equals"
        // → value1 required
        // → value2 required
        // → singleValue should NOT be set
      }
    ]
  }
}

Unary operator (isEmpty):

{
  "conditions": {
    "string": [
      {
        "operation": "isEmpty"
        // → value1 required
        // → value2 should NOT be set
        // → singleValue should be true (auto-added)
      }
    ]
  }
}

Dependency table:

Operator value1 value2 singleValue
equals Required Required false
notEquals Required Required false
contains Required Required false
isEmpty Required Hidden true
isNotEmpty Required Hidden true

Example 3: Slack Operation Matrix

Scenario: Different Slack operations show different fields

// post message
{
  "resource": "message",
  "operation": "post"
  // Shows: channel (required), text (required), attachments, blocks
}

// update message
{
  "resource": "message",
  "operation": "update"
  // Shows: messageId (required), text (required), channel (optional)
}

// delete message
{
  "resource": "message",
  "operation": "delete"
  // Shows: messageId (required), channel (required)
  // Hides: text, attachments, blocks
}

// get message
{
  "resource": "message",
  "operation": "get"
  // Shows: messageId (required), channel (required)
  // Hides: text, attachments, blocks
}

Field visibility matrix:

Field post update delete get
channel Required Optional Required Required
text Required Required Hidden Hidden
messageId Hidden Required Required Required
attachments Optional Optional Hidden Hidden
blocks Optional Optional Hidden Hidden

Nested Dependencies

What Are They?

Definition: Dependencies within object properties

Example: HTTP Request body.contentType controls body.content structure

{
  "body": {
    "contentType": "json",
    // → content expects JSON object
    "content": {
      "key": "value"
    }
  }
}

{
  "body": {
    "contentType": "form-data",
    // → content expects form fields array
    "content": [
      {
        "name": "field1",
        "value": "value1"
      }
    ]
  }
}

How to Handle

Strategy: Configure parent first, then children

// Step 1: Parent
{
  "body": {
    "contentType": "json"  // Set parent first
  }
}

// Step 2: Children (structure determined by parent)
{
  "body": {
    "contentType": "json",
    "content": {           // JSON object format
      "key": "value"
    }
  }
}

Auto-Sanitization and Dependencies

What Auto-Sanitization Fixes

Operator structure issues (IF/Switch nodes):

Example: singleValue property

// You configure (missing singleValue)
{
  "type": "boolean",
  "operation": "isEmpty"
  // Missing singleValue
}

// Auto-sanitization adds it
{
  "type": "boolean",
  "operation": "isEmpty",
  "singleValue": true  // ✅ Added automatically
}

What It Doesn't Fix

Missing required fields:

// You configure (missing channel)
{
  "resource": "message",
  "operation": "post",
  "text": "Hello"
  // Missing required field: channel
}

// Auto-sanitization does NOT add
// You must add it yourself
{
  "resource": "message",
  "operation": "post",
  "channel": "#general",  // ← You must add
  "text": "Hello"
}

Troubleshooting Dependencies

Problem 1: "Field X is required but not visible"

Error:

{
  "type": "missing_required",
  "property": "body",
  "message": "body is required"
}

But you don't see body field in configuration!

Solution:

// Check dependencies
const deps = get_property_dependencies({
  nodeType: "nodes-base.httpRequest"
});

// Find that body shows when sendBody=true
// Add sendBody
{
  "method": "POST",
  "sendBody": true,  // ← Now body appears!
  "body": {...}
}

Problem 2: "Field disappears when I change operation"

Scenario:

// Working configuration
{
  "resource": "message",
  "operation": "post",
  "channel": "#general",
  "text": "Hello"
}

// Change operation
{
  "resource": "message",
  "operation": "update",  // Changed
  "channel": "#general",  // Still here
  "text": "Updated"       // Still here
  // Missing: messageId (required for update!)
}

Validation error: "messageId is required"

Why: Different operation = different required fields

Solution:

// Check essentials for new operation
get_node_essentials({
  nodeType: "nodes-base.slack"
});

// Configure for update operation
{
  "resource": "message",
  "operation": "update",
  "messageId": "1234567890",  // Required for update
  "text": "Updated",
  "channel": "#general"       // Optional for update
}

Problem 3: "Validation passes but field doesn't save"

Scenario: Field hidden by dependencies after validation

Example:

// Configure
{
  "method": "GET",
  "sendBody": true,  // ❌ GET doesn't support body
  "body": {...}      // This will be stripped
}

// After save
{
  "method": "GET"
  // body removed because method=GET hides it
}

Solution: Respect dependencies from the start

// Correct approach
get_property_dependencies({
  nodeType: "nodes-base.httpRequest"
});

// See that body only shows for POST/PUT/PATCH/DELETE
// Use correct method
{
  "method": "POST",
  "sendBody": true,
  "body": {...}
}

Advanced Patterns

Pattern 1: Conditional Required with Fallback

Example: Channel can be string OR expression

// Option 1: String
{
  "channel": "#general"
}

// Option 2: Expression
{
  "channel": "={{$json.channelName}}"
}

// Validation accepts both

Pattern 2: Mutually Exclusive Fields

Example: Use either ID or name, not both

// Use messageId
{
  "messageId": "1234567890"
  // name not needed
}

// OR use messageName
{
  "messageName": "thread-name"
  // messageId not needed
}

// Dependencies ensure only one is required

Pattern 3: Progressive Complexity

Example: Simple mode vs advanced mode

// Simple mode
{
  "mode": "simple",
  "text": "{{$json.message}}"
  // Advanced fields hidden
}

// Advanced mode
{
  "mode": "advanced",
  "attachments": [...],
  "blocks": [...],
  "metadata": {...}
  // Simple field hidden, advanced fields shown
}

Best Practices

Do

  1. Check dependencies when stuck

    get_property_dependencies({nodeType: "..."});
    
  2. Configure parent properties first

    // First: method, resource, operation
    // Then: dependent fields
    
  3. Validate after changing operation

    // Operation changed → requirements changed
    validate_node_operation({...});
    
  4. Read validation errors for dependency hints

    Error: "body required when sendBody=true"
    → Hint: Set sendBody=true to enable body
    

Don't

  1. Don't ignore dependency errors

    // Error: "body not visible" → Check displayOptions
    
  2. Don't hardcode all possible fields

    // Bad: Adding fields that will be hidden
    
  3. Don't assume operations are identical

    // Each operation has unique requirements
    

Summary

Key Concepts:

  • displayOptions control field visibility
  • show = field appears when conditions match
  • hide = field disappears when conditions match
  • Multiple conditions = AND logic
  • Multiple values = OR logic

Common Patterns:

  1. Boolean toggle (sendBody → body)
  2. Resource/operation cascade (different operations → different fields)
  3. Type-specific config (string vs boolean conditions)
  4. Method-specific fields (GET vs POST)

Troubleshooting:

  • Field required but not visible → Check dependencies
  • Field disappears after change → Operation changed requirements
  • Field doesn't save → Hidden by dependencies

Tools:

  • get_property_dependencies - See dependency rules
  • get_node_essentials - See operation requirements
  • Validation errors - Hints about dependencies

Related Files: