windmill-labs/windmill · error · Error

No data table named '${name}' in this project

Error message

No data table named '${name}' in this project

What it means

runMigrationsFor resolves a data-table row by name from the wizard's rows list. It throws instead of returning because the function is also used as an appended wizard step, where a resolved promise is interpreted as 'migrations ran' — resolving for an unknown name would falsely report success over SQL that never executed.

Source

Thrown at frontend/src/lib/components/ImportSetupStep.svelte:636

			reusing = false
			working = false
		}
	}

	$effect(() => {
		void load()
	})

	/**
	 * The data table now exists — run the migrations that were skipped for it during the
	 * import, which is the whole reason this step waits for the configuration.
	 */
	async function runMigrationsFor(name: string): Promise<void> {
		const row = rows.find((r) => r.name === name)
		// Thrown, not returned: this also runs as the wizard's appended step, which reads a
		// resolved promise as "the migrations ran". Resolving for a name that matches no row
		// would report success over SQL that never executed.
		if (!row) throw new Error(`No data table named '${name}' in this project`)
		working = true
		row.status = 'running'
		try {
			for (const m of row.migrations) await applyOneMigration(workspace, slug, m)
			row.status = 'done'
			row.error = undefined
			// One-shot, cleared by name rather than by reference: `load()` rebuilds the row
			// objects, so the one holding the flag when it fires may not be this one.
			row.justSaved = true
			setTimeout(() => {
				const current = rows.find((r) => r.name === name)
				if (current) current.justSaved = false
			}, 1500)
		} catch (e: any) {
			row.status = 'failed'
			row.error = e?.body ?? e?.message ?? String(e)
			sendUserToast(`Could not run the migrations for ${name}: ${row.error}`, true)
			// Rethrown, because this also runs as the wizard's last checklist step

View on GitHub (pinned to e474e8803c)

Solutions

  1. Check the table name against the data tables listed in the import wizard (it must exactly match a row name)
  2. Re-load the project export so `rows` reflects the current tables, then retry
  3. If a custom step calls runMigrationsFor, update the name to the renamed/current table

Example fix

// before
await runMigrationsFor('users_old')
// after
if (rows.some(r => r.name === 'users')) await runMigrationsFor('users')
else sendUserToast(`No data table 'users' in this project`, true)
Defensive patterns

Strategy: validation

Validate before calling

if (!rows.some(r => r.name === name)) {
  throw new Error(`No data table named '${name}' in this project`)
}

Type guard

function rowExists(rows: {name: string}[], name: string): boolean {
  return rows.some((r) => r.name === name)
}

Try / catch

try {
  await runMigrationsFor(name)
} catch (e) {
  if (String(e.message).startsWith("No data table named")) {
    sendUserToast(e.message, true)
  } else throw e
}

Prevention

When it happens

Trigger: Calling runMigrationsFor(name) with a name that matches no row in `rows` — typically a stale retry button referencing a data table removed from the export, or a programmatic/step invocation with a wrong or renamed table name.

Common situations: Clicking 'retry' on a migration row after the export was re-imported with fewer/differently named tables; a customized wizard step passing a hard-coded table name; renamed data tables between hub project versions.

Related errors


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