Skip to content

[flow engine] Selectors don't support || and && operators — AI agents naturally write them #15

@lucasygu

Description

@lucasygu

Summary

The flow engine's selector parser treats the entire expression as a single dot-path lookup. When AI agents write natural JavaScript patterns like $.input.maxResults || 10 (default fallback) or $.input.email && $.input.email.length > 0 (conditional check), the engine tries to find an input named maxResults || 10 — which doesn't exist — and fails validation.

Reproduction

The || pattern (default values)

{
  "id": "search",
  "type": "action",
  "action": {
    "data": {
      "numResults": "$.input.maxResults || 10"
    }
  }
}

Validation error: Selector "$.input.maxResults || 10" references undefined input "maxResults || 10"

The && pattern (conditional checks)

{
  "id": "sendEmail",
  "type": "action",
  "if": "$.input.recipientEmail && $.input.recipientEmail.length > 0",
  "action": { ... }
}

Validation error: Selector "$.input.recipientEmail && $.input.recipientEmail.length > 0" references undefined input "recipientEmail && $"

Why AI agents write this

Both patterns are idiomatic JavaScript. When an AI agent designs a workflow with optional inputs, $.input.x || defaultValue is the natural way to express "use this input if provided, otherwise fall back to a default." Similarly, $.input.x && $.input.x.length > 0 is the natural null-safe check before using an optional string.

How often this happens

We built 65 n8n-replicated flows in a single session. This issue appeared in:

  • 2 flows with && in if conditions (go-to-marketing, research-agent)
  • 2 flows with || default fallbacks (google-maps-scraper, scrape-leads-google-maps)

That's 4 out of 65 (6%) — frequent enough that any batch of AI-generated flows will hit it.

Current workarounds

For || defaults: Declare the default in the input definition and reference $.input.x directly:

{
  "inputs": {
    "maxResults": { "type": "number", "default": 10 }
  },
  "steps": [{
    "action": { "data": { "numResults": "$.input.maxResults" } }
  }]
}

For && conditionals: Simplify to a truthy check:

{
  "if": "$.input.recipientEmail"
}

Suggested fix

Either:

Option A: Expand the selector parser to support || and && as JavaScript expressions (evaluate them at runtime instead of treating the whole string as a dot-path).

Option B: Document the limitation in the skill's selector syntax reference and add a validation error message that suggests the workaround:

Selector "$.input.maxResults || 10" contains unsupported operator "||". 
Use the "default" field on the input definition instead, or use a "code" step for complex expressions.

Option B is lower effort and would prevent AI agents from hitting a confusing error.

Related

This is the same class of issue as:

  • cli#6 (default values not resolved — now fixed in 1.14.1)
  • cli#12 (parseJson:true fails — skill teaches a pattern that doesn't work)

All three are cases where the flow engine's behavior surprises AI agents that write natural JavaScript patterns.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions