windmill-labs/windmill · warning
end '${idLabel(e)}' is only reachable through a skipped inpu
Error message
end '${idLabel(e)}' is only reachable through a skipped input/event handler — not run (bind it with --upload to include it). What it means
In `wmill pipeline run`, an --end that IS topologically downstream of --start can still be unreachable at runtime because the only path to it passes through an input/event handler that is skipped in CLI runs. Such ends are dropped from reachableEnds and this warning explains why, suggesting --upload to bind the handler and include it.
Source
Thrown at cli/src/commands/pipeline/pipeline.ts:859
droppedEnds = res.droppedEnds;
for (const d of droppedEnds) {
log.warn(`end '${idLabel(d)}' is not downstream of the start — ignored.`);
}
// Intersect the bounded window with the barrier-cut closure from the start so
// a barrier (or a node only reachable through one) inside the window is dropped.
const reachable = reachableCutting(dag, [start!], barriers);
selectedScripts = new Set(
scriptsOf([...res.nodes].filter((n) => reachable.has(n))),
);
// An end that boundedSet reached but the barrier cut removed is NOT satisfied:
// report it as dropped (not reachable) and warn, so `--json`/the plan don't
// claim a bound was met when its only path ran through a skipped handler.
for (const e of res.reachableEnds) {
if (reachable.has(e)) {
reachableEnds.push(e);
} else {
droppedEnds.push(e);
log.warn(
`end '${idLabel(e)}' is only reachable through a skipped input/event handler — not run (bind it with --upload to include it).`,
);
}
}
}
// Selections can still pull a non-runnable node in via graph reachability (e.g.
// whole-pipeline mode collects every root's closure) — drop macro libraries and
// local-only display nodes before ordering so they never run.
for (const p of notRunnablePaths) selectedScripts.delete(p);
const { order, cyclic } = topoOrder(graph, selectedScripts);
if (cyclic.length > 0) {
log.warn(`Skipping ${cyclic.length} script(s) on a dependency cycle: ${cyclic.sort().join(", ")}`);
}
// `// partitioned` scripts need a resolved `partition` arg. Deployed runs get
// it from backend run-start resolution, but previews (`--local`) never do —View on GitHub (pinned to e474e8803c)
Solutions
- Add --upload <handler-path>=<file/value> to bind the skipped input/event handler so its branch runs.
- Choose a different --end that doesn't depend on a skipped handler.
- Run the full pipeline segment in the UI (where handlers execute) if handler execution is required.
- Restructure the flow if this end should be runnable standalone without the handler.
Example fix
// before: end only reachable via skipped handler wmill pipeline run f/myflow --start preprocess --end report // after wmill pipeline run f/myflow --start preprocess --end report --upload f/myflow/input=data.csv
Defensive patterns
Strategy: validation
Validate before calling
// ensure ends don't depend on skipped handlers: inspect the path between start and end
// if any intermediate step is an input/event handler, add a --upload binding up front
const needsUpload = ['f/myflow/input']; // handler steps on the path
const uploadArgs = needsUpload.map(h => `--upload ${h}=<value>`).join(' '); Prevention
- Know which pipeline steps are input/event handlers; they don't run in CLI runs unless bound.
- Bind handlers with --upload whenever the selected window crosses one.
- Prefer ends on the main dependency chain for CLI runs.
- Check the run plan (--json) for dropped ends before executing.
When it happens
Trigger: Running with --end pointing at a node whose only incoming path runs through an input/event handler step (which doesn't execute in a local/CLI run unless bound via --upload).
Common situations: Selecting an end node that hangs off an event-triggered branch; trying to run a downstream node whose dependency is an upload-style input handler; forgetting that CLI runs skip input/event handlers by default.
Related errors
- end '${idLabel(d)}' is not downstream of the start — ignored
- Skipping ${cyclic.length} script(s) on a dependency cycle: $
- --upload for ${p} is unused — it isn't in the run selection.
- --arg for ${p} is unused — it isn't in the run selection.
- App ${appPath} not found
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/584af2ae09f71405.
Report an issue: GitHub.