windmill-labs/windmill · error

Failed to get Ducklake schema: <json of result>

Error message

Failed to get Ducklake schema: <json of result>

What it means

getDucklakeSchema() queries the Ducklake catalog for its schema; it accepts either an array of result rows or, defensively, a stringified-JSON payload (legacy duckdb-ffi behavior). If after normalization the schemas value is empty/falsy (empty array, null result, or unparsable payload) it throws with the raw JSON of the result for debugging.

Source

Thrown at frontend/src/lib/components/dbOps.ts:545

}: {
	workspace: string
	ducklake: string
	tag?: string
}): Promise<DBSchema> {
	let result = await runScriptAndPollResult({
		workspace,
		requestBody: {
			language: 'duckdb',
			content: `ATTACH 'ducklake://${ducklake}' AS __ducklake__; ${DUCKLAKE_GET_SCHEMA_QUERY}`,
			args: {},
			tag
		}
	})
	let schemas = Array.isArray(result) && result.length && (result?.[0]?.['result'] ?? {})
	// Safety for agent workers (duckdb ffi lib used to return JSON as stringified json)
	if (typeof schemas === 'string') schemas = JSON.parse(schemas)

	if (!schemas) throw new Error('Failed to get Ducklake schema: ' + JSON.stringify(result))
	assert('schemas is an object', typeof schemas === 'object')
	let schema: Omit<SQLSchema, 'stringified'> = {
		schema: schemas,
		publicOnly: false,
		lang: 'ducklake'
	}
	return { ...schema, stringified: stringifySchema(schema) }
}

// Returns every schema in the ducklake (including empty ones, e.g. freshly created)
// as a nested map { schema: { table: { column: {...} } } }.
const DUCKLAKE_GET_SCHEMA_QUERY = `
SELECT json_group_object(schema_name, COALESCE(schema_data, json_object())) AS result FROM (
	SELECT
		s.schema_name,
		(
			SELECT json_group_object(table_name, table_data) FROM (
				SELECT

View on GitHub (pinned to e474e8803c)

Solutions

  1. Inspect the JSON in the error message — it usually contains the actual duckdb error; fix that root cause first.
  2. Ensure the ducklake database is attached/initialized (run an internal DB operation that creates it) before requesting the schema.
  3. Check the duckdb/ducklake client version matches what the app expects; result-shape changes break the parse.
  4. Retry after the workspace's internal DB finishes provisioning if it was just created.

Example fix

// before
const schema = await getDucklakeSchema(workspace) // throws if ducklake not attached
// after
await ensureInternalDbInitialized(workspace) // attach ducklake first
const schema = await getDucklakeSchema(workspace)
Defensive patterns

Strategy: try-catch

Type guard

function isSchemaResult(result: unknown): boolean {
  const r = Array.isArray(result) ? result[0]?.['result'] : result
  const s = typeof r === 'string' ? safeParse(r) : r
  return s != null && typeof s === 'object'
}

Try / catch

try {
  const schema = await getDucklakeSchema(workspace)
} catch (e) {
  if (e.message.startsWith('Failed to get Ducklake schema')) {
    console.error('raw ducklake result:', e.message) // includes the JSON payload
    await ensureInternalDbInitialized(workspace)
  } else throw e
}

Prevention

When it happens

Trigger: Ducklake/duckdb query returned zero rows or an error payload instead of a schema result — e.g. the ducklake attachment does not exist, the internal DB is not initialized, or the duckdb ffi returned an unexpected shape that the string-parse fallback also failed to salvage.

Common situations: Querying schema before any internal DB/ducklake attachment is created; a duckdb-wasm/ffi version change altered the result shape; the underlying duckdb query failed silently and its error text ended up in `result`, making schemas falsy.

Related errors


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