windmill-labs/windmill · warning
WARNING: '${w.ws}' has an empty rule list — this DELETES ALL
Error message
WARNING: '${w.ws}' has an empty rule list — this DELETES ALL ${w.plan.toDelete.length} backend rule(s) for that workspace. What it means
`wmill protection-rules push` warns (in red, even with --yes) when a workspace's local rule list is empty while the backend still has rules for that workspace, because pushing would delete all of them. wipesAll marks plans where the push deletes every existing backend rule for a workspace.
Source
Thrown at cli/src/commands/protection-rules/push.ts:174
}
if (!opts.dryRun) {
outputResult(opts, {
success: true,
message: "No changes to push - all targeted workspaces are in sync",
});
}
return;
}
if (opts.dryRun) {
if (hadError) process.exit(1);
return;
}
// Pushing an empty list wipes a workspace's rules — be loud even with --yes.
for (const w of wsPlans) {
if (w.wipesAll) {
log.warn(
colors.red(
`WARNING: '${w.ws}' has an empty rule list — this DELETES ALL ${w.plan.toDelete.length} backend rule(s) for that workspace.`,
),
);
}
}
const totalDeletes = changed.reduce((n, w) => n + w.plan.toDelete.length, 0);
if (!opts.yes && !!process.stdin.isTTY) {
const confirmed = await Confirm.prompt({
message: totalDeletes > 0
? `Apply these changes? This DELETES ${totalDeletes} protection rule(s) across ${changed.length} workspace(s).`
: `Apply these changes to ${changed.length} workspace(s)?`,
default: totalDeletes === 0,
});
if (!confirmed) {
log.info("Operation cancelled");
return;View on GitHub (pinned to e474e8803c)
Solutions
- Abort and run `wmill protection-rules pull` first so the local file reflects backend state.
- Re-add the missing rules for that workspace in the local file before pushing.
- If the wipe is intentional, rerun with --yes (the warning still shows) — verify toDelete count matches expectations.
- Restrict the push to intended workspaces if your file is scoped per workspace.
Example fix
# before: rules.yaml has no rules for ws2 workspaces: ws1: [ ... ] # after: pull then push wmill protection-rules pull && wmill protection-rules push --yes
Defensive patterns
Strategy: validation
Validate before calling
// abort a wipe-causing push before it happens
import { readFileSync } from 'fs';
const local = parseRules(readFileSync('protection-rules.yaml', 'utf-8'));
for (const ws of workspacesInScope) {
const backendCount = await fetchBackendRuleCount(ws);
if ((local[ws] ?? []).length === 0 && backendCount > 0) {
throw new Error(`refusing push: would delete all ${backendCount} rules for ${ws}; pull first`);
}
} Try / catch
// if you must push programmatically, treat the warning as a gate
if (plan.wipesAll && !process.env.CONFIRM_WIPE) {
throw new Error(`${plan.ws}: push would delete all backend rules — set CONFIRM_WIPE to proceed`);
} Prevention
- Always `pull` before `push` when the local file may be stale.
- Never hand-delete a whole workspace block from the rules file without checking the backend.
- Review the WARNING line even when using --yes.
- Scope pushes to the workspaces you actually edited.
When it happens
Trigger: Running push with a local rules file where some workspace has zero rules while that workspace has N > 0 rules on the server; typically the local file only covers some workspaces or rules were never pulled.
Common situations: Fresh checkout with an empty/stale rules file pushed to a configured workspace; editing the YAML and accidentally deleting a workspace's rule block; pushing before running pull to sync.
Related errors
- Workspace folder not found, are you in the right directory?
- Not a fileset resource path: ${changePath}
- No resource metadata file found for fileset resource: ${chan
- Found ${wrongFormatPaths.length} directory(ies) using ${foun
- pointerErrors.join("\n")
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/488f98b071cf5c2a.
Report an issue: GitHub.