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

  1. Pass the specific `.schedule.yaml` file: `wmill schedule push ./schedules/nightly.schedule.yaml`
  2. Loop over files to push a directory's worth: `for f in ./schedules/*.schedule.yaml; do wmill schedule push "$f"; done`
  3. 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

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


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/cf3bbb2984864477. Report an issue: GitHub.