Structural Validation

Structural errors (DIP001–DIP010) — the 10 checks a workflow must pass to run.

Overview

Dippin provides two levels of analysis:

Structural validation (DIP001-DIP010): Errors that must be fixed. A workflow with any of these cannot execute. Run with dippin validate.

Semantic linting (DIP101-DIP162): Warnings that flag likely bugs or questionable patterns. They don’t block execution but should be reviewed. Run with dippin lint for both levels.

Diagnostic Format

Diagnostics are displayed in a rustc-inspired format:

error[DIP003]: unknown node reference "InterpretX" in edge
  --> pipeline.dip:45:5
  = help: did you mean "Interpret"?

Structural Errors (DIP001-DIP010)

These must be fixed for a workflow to be valid. Each causes exit code 1.

DIP001 — Start Node Missing

The workflow must declare a start: field pointing to an existing node.

error[DIP001]: start node does not exist
  --> pipeline.dip:1:1
  = help: add "start: <NodeID>" to the workflow header
DIP002 — Exit Node Missing

The workflow must declare an exit: field pointing to an existing node.

error[DIP002]: exit node does not exist
  --> pipeline.dip:1:1
  = help: add "exit: <NodeID>" to the workflow header
DIP003 — Unknown Node Reference in Edge

Every edge's From and To must reference existing node IDs. The validator uses Levenshtein distance to suggest corrections for typos.

error[DIP003]: unknown node reference "InterpretX" in edge
  --> pipeline.dip:45:5
  = help: did you mean "Interpret"?
DIP004 — Unreachable Node from Start

Every node must be reachable from the start node via some path of edges. BFS from the start node cannot reach this node.

error[DIP004]: node unreachable from start
  --> pipeline.dip:20:3
  = help: add an edge leading to this node, or remove it
DIP005 — Unconditional Cycle Detected

The workflow graph must be a DAG, with the exception of restart edges. A back-edge not marked restart: true would loop forever.

error[DIP005]: unconditional cycle detected
  --> pipeline.dip:50:5
  = help: remove an edge in this cycle or mark it "restart: true"
DIP006 — Exit Node Has Outgoing Edges

The exit node is the terminal — it must have zero outgoing edges.

error[DIP006]: exit node has outgoing edges
  --> pipeline.dip:55:5
  = help: remove outgoing edges from the exit node
DIP007 — Parallel/Fan-In Mismatch

Every parallel node must have a matching fan_in node with the same set of branch nodes.

error[DIP007]: parallel fan-out/fan-in mismatch
  --> pipeline.dip:15:3
  = help: add a matching fan_in node
DIP008 — Duplicate Node ID

Node IDs must be globally unique within a workflow.

error[DIP008]: duplicate node ID
  --> pipeline.dip:30:3
  = help: rename this node or remove the duplicate
DIP009 — Duplicate Edge

No two edges may have the same (from, to, condition) combination. Edges with different conditions on the same pair are not duplicates.

error[DIP009]: duplicate edge
  --> pipeline.dip:60:5
  = help: remove the duplicate edge
DIP010 — Unparseable Edge Condition

Every edge when condition must parse into a valid expression. An unparseable condition — an unknown operator, or a tool-node field like marker_grep used in operator position — leaves the edge's routing undefined, so the workflow cannot execute. One diagnostic fires per bad edge; every parseable edge is still checked.

error[DIP010]: edge A -> Z: invalid condition "marker_grep \"^ok\"": unknown operator "^ok"
  --> pipeline.dip:14:5
  = help: valid operators: = == != contains startswith endswith in