windmill-labs/windmill · error
file path must refer to a file.
Error message
file path must refer to a file.
What it means
Thrown by the Windmill CLI's `schedule push` command when the local argument does not point to a regular file. It stats filePath and requires isFile(); passing a directory (or another non-regular file) aborts the push with this error instead of attempting to read a schedule definition from it.
Source
Thrown at cli/src/commands/schedule/schedule.ts:311
workspace: workspace.workspaceId,
path,
requestBody: { enabled: false },
});
log.info(colors.yellow(`Schedule ${path} disabled.`));
}
async function push(opts: GlobalOptions, filePath: string, remotePath: string) {
const workspace = await resolveWorkspace(opts);
await requireLogin(opts);
if (!validatePath(remotePath)) {
return;
}
const fstat = await stat(filePath);
if (!fstat.isFile()) {
throw new Error("file path must refer to a file.");
}
console.log(colors.bold.yellow("Pushing schedule..."));
await pushSchedule(
workspace.workspaceId,
remotePath,
undefined,
parseFromFile(filePath)
);
console.log(colors.bold.underline.green("Schedule pushed"));
}
const command = new Command()
.description("schedule related commands")
.option("--json", "Output as JSON (for piping to jq)")
.action(list as any)
.command("list", "list all schedules")View on GitHub (pinned to e474e8803c)
Solutions
- Pass the specific `.schedule.yaml` file: `wmill schedule push ./schedules/nightly.schedule.yaml`
- Loop over files to push a directory's worth: `for f in ./schedules/*.schedule.yaml; do wmill schedule push "$f"; done`
- Verify the argument resolves to a regular file (`test -f`) in scripts before invoking push
Example fix
// before wmill schedule push ./schedules/ // after wmill schedule push ./schedules/nightly.schedule.yaml // or bulk: for f in ./schedules/*.schedule.yaml; do wmill schedule push "$f"; done
Defensive patterns
Strategy: validation
Validate before calling
import { statSync } from 'fs';
const st = statSync(localPath);
if (!st.isFile()) {
throw new Error(`schedule push expects a .schedule.yaml file, got: ${localPath}`);
} Type guard
import { statSync } from 'fs';
function isFile(p: string): boolean {
try { return statSync(p).isFile(); } catch { return false; }
} Try / catch
try {
await wmill.schedule.push(localPath);
} catch (e) {
if ((e as Error).message === 'file path must refer to a file.') {
console.error(`${localPath} is a directory; push individual .schedule.yaml files (loop over a glob for bulk)`);
} else throw e;
} Prevention
- Always pass a single `.schedule.yaml` file — `schedule push` does not accept directories
- Use a shell loop (`for f in dir/*.schedule.yaml`) for bulk pushes
- Guard scripts with `test -f "$path"` before calling push
- Watch shell tab-completion so it does not silently select the directory
When it happens
Trigger: Running `wmill schedule push <localPath>` where localPath is a directory such as the folder containing many `.schedule.yaml` files (the command does not recurse or batch), or a symlink to a directory. A nonexistent path fails earlier in stat with ENOENT.
Common situations: Trying to push a whole folder of schedules with one command; shell tab-completion selecting the directory; scripts interpolating a directory variable; confusing `schedule push` (single file) with a bulk sync command.
Related errors
- file path must refer to a file.
- File already exists: + filePath
- File already exists: + filePath
- File not found: ${filePath}
- Workspace folder not found, are you in the right directory?
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/cf3bbb2984864477.
Report an issue: GitHub.