windmill-labs/windmill · error

File already exists: + filePath

Error message

File already exists: + filePath

What it means

Thrown by `wmill schedule new` when the target schedule file already exists on disk. The command builds filePath as '<path>.schedule.yaml' and stats it; a successful stat means the file exists, so the CLI throws rather than overwriting an existing schedule definition.

Source

Thrown at cli/src/commands/schedule/schedule.ts:63

    console.log(JSON.stringify(schedules));
  } else {
    new Table()
      .header(["Path", "Schedule"])
      .padding(2)
      .border(true)
      .body(schedules.map((x) => [x.path, x.schedule]))
      .render();
  }
}

async function newSchedule(opts: GlobalOptions, path: string) {
  if (!validatePath(path)) {
    return;
  }
  const filePath = path + ".schedule.yaml";
  try {
    await stat(filePath);
    throw new Error("File already exists: " + filePath);
  } catch (e: any) {
    if (e.message?.startsWith("File already exists")) throw e;
  }
  const template: ScheduleFile = {
    schedule: "0 0 */6 * * *",
    on_failure: "",
    script_path: "",
    args: {},
    timezone: "Etc/UTC",
    is_flow: false,
    enabled: false,
  };
  await mkdir(dirname(filePath), { recursive: true });
  await writeFile(filePath, yamlStringify(template as Record<string, any>), {
    flag: "wx",
    encoding: "utf-8",
  });
  log.info(colors.green(`Created ${filePath}`));

View on GitHub (pinned to e474e8803c)

Solutions

  1. Edit the existing <path>.schedule.yaml (schedule, cron, is_enabled, etc.) instead of re-running `schedule new`
  2. Remove or rename the existing file (`git rm` / `git mv`) if regeneration is intended
  3. Use `wmill schedule push` on the edited file to update the remote schedule

Example fix

// before
$ wmill schedule new u/admin/nightly
Error: File already exists: u/admin/nightly.schedule.yaml
// after: edit u/admin/nightly.schedule.yaml, then
$ wmill schedule push u/admin/nightly.schedule.yaml
Defensive patterns

Strategy: try-catch

Validate before calling

import { statSync } from 'fs';

const filePath = path + '.schedule.yaml';
let exists = false;
try { statSync(filePath); exists = true; } catch { /* ENOENT: safe */ }
if (exists) throw new Error(`refusing: ${filePath} already exists`);

Try / catch

try {
  await wmill.schedule.new(path, ...);
} catch (e) {
  if ((e as Error).message.startsWith('File already exists')) {
    // edit the existing .schedule.yaml (e.g. change cron) and `schedule push` instead
  } else throw e;
}

Prevention

When it happens

Trigger: Running `wmill schedule new <path>` where `<path>.schedule.yaml` already exists; re-running a scaffolding script; choosing a path that differs textually ('./x', 'a/../x') but resolves to an existing file.

Common situations: Re-running project bootstrap scripts; wanting to change a schedule but using `new` instead of editing the existing YAML or pushing; cron-pattern iteration where you recreate schedules repeatedly; forgetting the `.schedule.yaml` suffix is appended so the intended unique path collides.

Understand the failure class

Background: "already exists" / EEXIST / FileAlreadyExistsException: what the 'file already exists' error means and how to fix it — this error's family across 37 libraries.

Related errors


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