windmill-labs/windmill · warning
end '${idLabel(d)}' is not downstream of the start — ignored
Error message
end '${idLabel(d)}' is not downstream of the start — ignored. What it means
In `wmill pipeline run`, when an --end target is not downstream of the resolved --start node, boundedSet drops it and this warning names each dropped end. The run still proceeds with the reachable window; the unreachable --end is simply ignored.
Source
Thrown at cli/src/commands/pipeline/pipeline.ts:843
),
);
let selectedScripts: Set<string>;
let reachableEnds: string[] = [];
let droppedEnds: string[] = [];
if (runAll) {
// Whole pipeline = everything reachable from the valid starts (schedule/manual
// roots), cutting at the barriers above. A node reachable via another,
// non-barrier path still runs.
selectedScripts = new Set(scriptsOf(reachableCutting(dag, starts, barriers)));
} else if (ends.length === 0) {
// No bound → full read-aware downstream of start (pure readers included),
// still cut at barriers so an event/upload descendant isn't run empty.
selectedScripts = new Set(scriptsOf(reachableCutting(dag, [start!], barriers)));
} else {
const res = boundedSet(dag, start!, ends);
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).`,
);View on GitHub (pinned to e474e8803c)
Solutions
- Fix the --end value to a path/id that is downstream of --start (check the pipeline graph in the UI).
- Remove the invalid --end and rerun without it.
- Verify the script path exists and wasn't renamed (wmill pipeline script list or the UI).
- If you meant a different starting point, adjust --start so the end is actually reachable.
Example fix
// before wmill pipeline run f/myflow --start preprocess --end trainning # typo, not downstream // after wmill pipeline run f/myflow --start preprocess --end training
Defensive patterns
Strategy: validation
Validate before calling
// verify ends are downstream of start using the plan output before running
const plan = JSON.parse(execSync(`wmill pipeline run f/x --start ${start} --end ${end} --json --dry-run 2>/dev/null`).toString());
if (plan.droppedEnds?.length) throw new Error(`invalid --end: ${plan.droppedEnds.join(',')}`); Prevention
- Validate --start/--end against the pipeline graph in the UI before running.
- Use exact script paths/ids, not display names.
- Update run scripts after renaming flow steps.
- Use --json output to confirm droppedEnds is empty.
When it happens
Trigger: Running a sub-window of a pipeline with --start X --end Y where Y is not reachable from X in the pipeline DAG (typo in the end path/name, or ends that sit on a parallel branch).
Common situations: Misspelled or stale script path passed to --end after refactoring the flow; assuming --end accepts multiple arbitrary nodes rather than descendants of --start; copy-pasting ends from a different pipeline.
Related errors
- end '${idLabel(e)}' is only reachable through a skipped inpu
- 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.
- Invalid trigger kind: ${opts.kind}. Valid kinds: ${TRIGGER_T
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/85cd2c1ad3e92c3d.
Report an issue: GitHub.