# How Modly Validates Workflow Wiring and Detects Invalid Node Connections

> Modly validates workflow wiring with pre-flight analysis, detecting invalid node connections, missing inputs, and illegal merges before execution starts. Learn how.

- Repository: [lightningpixel/modly](https://github.com/lightningpixel/modly)
- Tags: internals
- Published: 2026-08-15

---

**Modly validates workflow wiring through a static "pre-flight" analysis that inspects node connections, resolves data types through passthrough chains, and detects specific wiring errors like missing inputs or illegal Wait branch merges before execution begins.**

Modly, an open-source workflow engine maintained by **lightningpixel/modly**, ensures reliable pipeline execution by validating node connections prior to runtime. The system performs a comprehensive static analysis to catch wiring errors—such as type mismatches, disconnected inputs, or invalid branch merges—preventing runtime failures in complex creative workflows.

## The Pre-Flight Validation Architecture

The validation logic centers on `validateWorkflowPreflight` in [`src/areas/workflows/preflight.ts`](https://github.com/lightningpixel/modly/blob/main/src/areas/workflows/preflight.ts). This function orchestrates type resolution and error detection by collaborating with utility functions in [`src/areas/workflows/nodeBehaviors.ts`](https://github.com/lightningpixel/modly/blob/main/src/areas/workflows/nodeBehaviors.ts). Together, these modules create a **pre-flight validation** system that analyzes the workflow graph without executing it.

## Collecting and Resolving Data Types

Before detecting connection errors, Modly must determine what data type each node produces.

### Determining Node Output Types

The `getNodeOutputType` function in [`preflight.ts`](https://github.com/lightningpixel/modly/blob/main/preflight.ts) inspects each node's intrinsic type to establish its output data type. For built-in nodes, this returns standard types like `image`, `text`, `mesh`, or `audio`. For extension nodes, the function reads the extension's declared output type from its manifest. These mappings are stored in a `Map<string, DataType>` called `outputTypes` for O(1) lookup during subsequent validation steps.

### Resolving Passthrough Data Sources

Passthrough nodes—such as *wait* nodes—forward data without transformation, complicating type tracking. The `resolveDataSource` helper (in [`nodeBehaviors.ts`](https://github.com/lightningpixel/modly/blob/main/nodeBehaviors.ts)) traverses backwards through consecutive passthrough nodes until it locates the actual source node. Once identified, the source's output type propagates to the passthrough node, ensuring type consistency throughout the chain.

## Detecting Specific Wiring Problems

With type information resolved, `validateWorkflowPreflight` iterates through every node to identify specific connection errors.

### Missing Scene Resources and Empty Folders

The validator checks for configuration errors in specialized nodes. A `meshNode` configured to "Current Scene" must provide a valid mesh URL; otherwise, the system generates a **missing current mesh** error. Similarly, For-Each nodes must specify a folder path—the validator flags **empty folder** selections as wiring issues before execution.

### Illegal Wait Branch Merging

Using the `nearestUpstreamWaits` helper in [`nodeBehaviors.ts`](https://github.com/lightningpixel/modly/blob/main/nodeBehaviors.ts), Modly detects when a node consumes inputs from multiple upstream Wait branches. This pattern is **illegal** because the node would trigger before any branch produces a mesh, resulting in undefined behavior. The validator flags such connections immediately, preventing race conditions in asynchronous workflows.

### Extension Node Connection Validation

Extension nodes undergo rigorous input validation to ensure compatibility with the underlying extension:

- **Extension existence** – The validator confirms the `extensionId` references a loaded extension from the installed extensions list.
- **Required input coverage** – For each required input type declared by the extension, the system verifies at least one incoming edge provides a matching output type from the `outputTypes` map.
- **Type mismatch detection** – If an incoming edge supplies a type not accepted by the extension (e.g., feeding `audio` into an extension expecting only `image`), the validator records a specific type mismatch error.

## Issue Aggregation and Reporting

All detected problems accumulate in the `issues` array as `WorkflowPreflightIssue` objects. Each issue contains a unique key, a human-readable message, and the offending node ID. The `pushIssue` utility prevents duplicate entries when multiple validation checks identify the same problem. The `validateWorkflowPreflight` function returns this array—an empty array indicates valid workflow wiring ready for execution.

## Practical Implementation Example

Here's how to invoke the validator in your own Modly implementation:

```typescript
import { validateWorkflowPreflight } from '@/areas/workflows/preflight'
import { getWorkflowExtension } from '@/areas/workflows/mockExtensions'

// Example workflow (simplified)
const workflow = {
  nodes: [
    { id: '1', type: 'imageNode', data: {} },
    { id: '2', type: 'extensionNode', data: { extensionId: 'myExt' } },
    { id: '3', type: 'outputNode', data: {} },
  ],
  edges: [
    { id: 'e1', source: '1', target: '2' },
    { id: 'e2', source: '2', target: '3' },
  ],
}

// Load all installed extensions (mocked here)
const allExtensions = [getWorkflowExtension('myExt', [])].filter(Boolean)

// Run the pre‑flight validator
const issues = validateWorkflowPreflight(workflow, allExtensions)

// `issues` will be empty if wiring is correct, otherwise it contains descriptive errors.
if (issues.length) {
  console.warn('Workflow has wiring problems:', issues)
} else {
  console.log('Workflow wiring is valid!')
}

```

## Summary

- Modly performs **static pre-flight validation** in `validateWorkflowPreflight` before executing any workflow.
- Type resolution relies on `getNodeOutputType` and `resolveDataSource` to handle passthrough chains correctly.
- The system detects **missing inputs**, **type mismatches**, and **illegal Wait branch merges** using `nearestUpstreamWaits`.
- Extension nodes undergo specialized validation for existence and input compatibility.
- All issues aggregate as `WorkflowPreflightIssue` objects, enabling clear debugging feedback.

## Frequently Asked Questions

### What happens if Modly detects invalid node connections during validation?

If `validateWorkflowPreflight` returns a non-empty `issues` array, the workflow execution is blocked and the interface displays descriptive error messages for each `WorkflowPreflightIssue`. Users must resolve missing inputs, type mismatches, or illegal branch merges before the workflow can run.

### How does Modly handle data types through passthrough nodes?

Modly uses the `resolveDataSource` helper in [`nodeBehaviors.ts`](https://github.com/lightningpixel/modly/blob/main/nodeBehaviors.ts) to trace backwards through passthrough nodes (like Wait nodes) until finding the actual source. The source's output type then propagates forward, ensuring downstream nodes receive correct type information regardless of intermediate passthrough chains.

### Can Modly validate custom extension nodes?

Yes. The validator specifically handles `extensionNode` types by checking that the referenced extension is loaded and that all required inputs are satisfied by incoming edges with compatible types. This prevents runtime errors when third-party extensions receive unexpected data formats.

### Where is the workflow validation logic located in the Modly repository?

The core validation logic resides in [`src/areas/workflows/preflight.ts`](https://github.com/lightningpixel/modly/blob/main/src/areas/workflows/preflight.ts), with supporting graph traversal utilities in [`src/areas/workflows/nodeBehaviors.ts`](https://github.com/lightningpixel/modly/blob/main/src/areas/workflows/nodeBehaviors.ts). Type definitions for workflows and nodes are found in [`src/shared/types/electron.d.ts`](https://github.com/lightningpixel/modly/blob/main/src/shared/types/electron.d.ts).