{"record":{"id":"91c11d79c61e5ead","repo":"windmill-labs/windmill","slug":"workspace-already-has-datatable-s-existing-map","errorCode":null,"errorMessage":"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)","messagePattern":"Workspace already has datatable\\(s\\): (.+?)\\. Re-run with --force to add '(.+?)' \\(note: fork metadata on existing datatables is not preserved\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/src/commands/datatable/datatable.ts","lineNumber":132,"sourceCode":"async function create(\n  opts: GlobalOptions & { resource?: string; force?: boolean },\n  name?: string,\n) {\n  const workspace = await resolveWorkspace(opts);\n  await requireLogin(opts);\n  const dtName = name ?? DEFAULT_DATATABLE_NAME;\n\n  const existing = await wmill.listDataTables({\n    workspace: workspace.workspaceId,\n  });\n  if (existing.some((d) => d.name === dtName)) {\n    throw new Error(`Datatable '${dtName}' already exists in this workspace`);\n  }\n  // edit_datatable_config replaces the whole settings object, and fork\n  // metadata on existing datatables can't be read back through the API —\n  // so only touch a non-empty config when explicitly asked to.\n  if (existing.length > 0 && !opts.force) {\n    throw new Error(\n      `Workspace already has datatable(s): ${existing\n        .map((d) => d.name)\n        .join(\", \")}. Re-run with --force to add '${dtName}' ` +\n        \"(note: fork metadata on existing datatables is not preserved)\",\n    );\n  }\n\n  const datatables: Record<\n    string,\n    { database: { resource_type: \"postgresql\" | \"instance\"; resource_path?: string } }\n  > = {};\n  for (const d of existing) {\n    datatables[d.name] = {\n      database: {\n        resource_type: d.resource_type as \"postgresql\" | \"instance\",\n        resource_path: d.resource_path ?? undefined,\n      },\n    };","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/cli/src/commands/datatable/datatable.ts#L114-L150","documentation":"`wmill datatable create` also refuses to touch a workspace that already has ANY datatables unless `--force` is passed, because the create path rewrites the workspace datatable config wholesale and fork metadata on existing datatables cannot be read back through the API. This guards against silently losing per-datatable settings when adding a datatable to a non-empty workspace.","triggerScenarios":"Running `wmill datatable create <name>` in a workspace where `listDataTables` returns at least one datatable (and the requested name itself doesn't collide) without the `--force` flag.","commonSituations":"Adding a second datatable to a shared workspace that was set up by `wmill datatable init`-style tooling; workspaces whose datatables carry fork metadata that a blind config rewrite would destroy.","solutions":["Re-run with `--force`: `wmill datatable create <name> --force` (accepting that fork metadata on existing datatables is not preserved).","Create the datatable in a fresh/empty workspace if preserving metadata matters.","Recreate the fork metadata manually after a forced create, if unavoidable."],"exampleFix":"// before\nwmill datatable create analytics\n// after\nwmill datatable create analytics --force","handlingStrategy":"validation","validationCode":"const existing = await wmill.listDataTables({ workspace });\nif (existing.length > 0 && !process.env.FORCE_DT) throw new Error('workspace not empty; pass --force intentionally');","typeGuard":"null","tryCatchPattern":"try { await create() } catch (e) { if (String(e).includes('Re-run with --force')) promptUserForForce(); else throw e; }","preventionTips":["Read the error fully — it lists existing datatables and the exact flag needed","Understand that --force drops fork metadata before using it","Create additional datatables in dedicated workspaces when metadata preservation matters"],"tags":["cli","datatable","guard","force-flag"],"backgroundTag":"destructive-operation-guard","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}