windmill-labs/windmill · error · Error
Could not verify triggers for
Error message
Could not verify triggers for ${r.path} (${e?.body ?? e?.message ?? e}) — aborting so an input-only entrypoint isn't run with empty args; retry once resolved. What it means
Deliberately fail-closed error from enrichDeployedNonAutorunTriggers (used by `wmill pipeline run`). Before auto-running a deployed pipeline entrypoint that is not marked auto-run, the CLI fetches the script body to check for input-only trigger markers; if that fetch fails it aborts, because running an input-only entrypoint with empty args could execute unintended work. The error names the offending path and embeds the underlying cause, and tells the user to retry once resolved.
Solutions
- Read the parenthesized cause: 404 -> fix or re-pull the pipeline so the referenced script path exists in the workspace.
- 401/403 -> re-authenticate or grant the token read access to the script, then retry the command.
- Network/5xx cause -> wait for the server to recover and re-run; the command is safe to retry since it aborted before executing anything.
- Verify the intended workspace with `wmill workspace show` if the path was recently pulled from a different one.
Example fix
// before: script renamed on server wmill pipeline run f/old_entrypoint // after wmill pipeline pull # refresh local state wmill pipeline run f/new_entrypoint
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the entrypoint is readable before attempting a run
try {
await wmill.getScriptByPath({ workspace: ws, path: entrypointPath });
} catch (e) {
throw new Error(`Entrypoint ${entrypointPath} not verifiable — fix before running`);
} Try / catch
try {
await runPipeline(opts);
} catch (e: any) {
if (e.message.includes("Could not verify triggers")) {
const cause = /\((.+)\)/.exec(e.message)?.[1];
if (cause?.includes("404")) console.error("Re-pull: referenced script no longer exists");
else console.error("Transient/read failure — safe to retry after resolving:", cause);
}
throw e;
} Prevention
- Run `wmill pipeline pull` after renaming or deleting referenced scripts so local paths stay in sync.
- Ensure the token has read access to every script in the pipeline.
- Confirm the active workspace matches the one the pipeline was pulled from.
When it happens
Trigger: Running `wmill pipeline run <path>` when `wmill.getScriptByPath` fails for the entrypoint: 404 (script path no longer exists in the workspace), 401/403 (token lacks read access), 5xx, or a network failure mid-run.
Common situations: The pipeline references a script that was renamed or deleted after local pull; the CLI token is read-scoped differently than expected; the workspace was switched between pull and run; flaky connectivity in CI.
Related errors
- Cannot fetch backend version from
- Cannot fetch latest CLI version on npmjs to check if…
- connection error
- Could not auto-fill missing lockfile entries
- Could not check backend for git-sync settings
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/ffa5b86f83635a64.
Report an issue: GitHub.
Appendix: source
Thrown at cli/src/commands/pipeline/pipeline.ts:241
graph: BCGraph,
): Promise<void> {
const scripts = (graph.runnables ?? []).filter((r) => r.usage_kind === "script");
await Promise.all(
scripts.map(async (r) => {
const known = new Set(
(graph.triggers ?? [])
.filter((t) => t.runnable_path === r.path && MARKER_KINDS.has(t.trigger_kind))
.map((t) => t.trigger_kind),
);
let script;
try {
script = await wmill.getScriptByPath({ workspace: workspaceId, path: r.path });
} catch (e: any) {
// Fail CLOSED: if we can't read a script's body we can't rule out a
// marker-only input trigger, so aborting is safer than auto-running it
// with empty args. (The `show` enrichment stays best-effort — it only
// affects the rendered tree, not what runs.)
throw new Error(
`Could not verify triggers for ${r.path} (${e?.body ?? e?.message ?? e}) — ` +
`aborting so an input-only entrypoint isn't run with empty args; retry once resolved.`,
);
}
for (const kind of recoverHeaderMarkers(script.content ?? "")) {
if (known.has(kind)) continue;
known.add(kind);
graph.triggers.push({
trigger_kind: kind,
runnable_kind: "script",
runnable_path: r.path,
});
}
}),
);
}
// Index a pipeline graph and render its DAG as an ASCII tree. Shared by theView on GitHub (pinned to e474e8803c)