Workflow tool: pipeline() silently skips remaining stages when a stage resolves to null (not throw)

Open 💬 0 comments Opened Jul 8, 2026 by anombyte93

Environment

Claude Code CLI, model claude-fable-5, Workflow (multi-agent orchestration) tool.

Repro

A two-stage pipeline where stage 1 conditionally does no work and resolves null:

const results = await pipeline(
  items,
  (item) => item.needsCommit ? agent(commitPrompt(item), {...}) : Promise.resolve(null),
  (prev, item) => item.needsTriage ? agent(triagePrompt(item), {...}) : Promise.resolve({item, prev})
)

Observed

Every item whose stage 1 resolved null never executed stage 2. In a 57-item run, 37 triage-only items were silently dropped — the workflow completed "successfully" with 20/57 stage-2 executions and no error, warning, or log line.

Expected

Docs say: "A stage that throws drops that item to null and skips its remaining stages." A stage that resolves null is a legitimate value and later stages should still run with prevResult === null (they already receive originalItem/index precisely so they don't depend on prev).

Why it matters

This is silent-loss-of-work in the tool's core primitive: the run reports success while a majority of items were never processed. It also composes badly with agent() legitimately returning null on user-skip.

Workaround

Never resolve null from a stage — return a sentinel object like {skipped: true}.

Suggested fix

Only skip remaining stages on throw (as documented), or at minimum log() a per-item notice when items are dropped by null-propagation.

View original on GitHub ↗