windmill-labs/windmill · error

Datatable '${dtName}' already exists in this workspace

Error message

Datatable '${dtName}' already exists in this workspace

What it means

`wmill datatable create` refuses to create a datatable whose name already exists in the target workspace. Before creating, it lists existing datatables via `wmill.listDataTables` and throws if one matches the requested name (default 'main').

Source

Thrown at cli/src/commands/datatable/datatable.ts:126

  .option(
    "-d --datatable <datatable:string>",
    "Target datatable (default: main)",
  )
  .action(migrateDown as any);

async function create(
  opts: GlobalOptions & { resource?: string; force?: boolean },
  name?: string,
) {
  const workspace = await resolveWorkspace(opts);
  await requireLogin(opts);
  const dtName = name ?? DEFAULT_DATATABLE_NAME;

  const existing = await wmill.listDataTables({
    workspace: workspace.workspaceId,
  });
  if (existing.some((d) => d.name === dtName)) {
    throw new Error(`Datatable '${dtName}' already exists in this workspace`);
  }
  // edit_datatable_config replaces the whole settings object, and fork
  // metadata on existing datatables can't be read back through the API —
  // so only touch a non-empty config when explicitly asked to.
  if (existing.length > 0 && !opts.force) {
    throw new Error(
      `Workspace already has datatable(s): ${existing
        .map((d) => d.name)
        .join(", ")}. Re-run with --force to add '${dtName}' ` +
        "(note: fork metadata on existing datatables is not preserved)",
    );
  }

  const datatables: Record<
    string,
    { database: { resource_type: "postgresql" | "instance"; resource_path?: string } }
  > = {};
  for (const d of existing) {

View on GitHub (pinned to e474e8803c)

Solutions

  1. Run `wmill datatable list` to confirm the datatable exists; if it's the one you want, skip creation.
  2. Use a different name for the new datatable.
  3. If you intended to recreate/replace, delete the existing datatable first, then create.

Example fix

// before
await $`wmill datatable create main`;
// after
await $`wmill datatable list || wmill datatable create main`;
Defensive patterns

Strategy: validation

Validate before calling

const existing = await wmill.listDataTables({ workspace });
if (existing.some(d => d.name === name)) console.log('datatable exists, skipping create');

Type guard

null

Try / catch

try { await wmill.datatableCreate(name) } catch (e) { if (String(e).includes('already exists')) return; throw e; }

Prevention

When it happens

Trigger: Running `wmill datatable create` (with or without an explicit name) when `listDataTables` already returns a datatable with that name — most commonly re-running the create command twice, or creating the default 'main' datatable in a workspace that already has it.

Common situations: Idempotent setup scripts run twice; onboarding docs that tell users to create 'main' while the workspace was provisioned with it already; switching workspaces accidentally and re-creating.

Related errors


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