windmill-labs/windmill · error

App " " has no backend runnable " ". Available runnables: .

Error message

App "${path}" has no backend runnable "${key}". Available runnables: ${known.join(', ')}.

What it means

Thrown by testRunAppRunnable in the global AI chat when the requested runnable `key` does not exist in the app draft's runnables map. The tool executes one backend runnable in preview mode; because the key comes from model output, the error deliberately lists every known runnable key so the model can correct itself and re-invoke with a valid one.

Solutions

  1. Retry with one of the keys listed in the error's 'Available runnables' section
  2. Re-read the app draft to get the current runnables map and pick the correct key
  3. If the runnable should exist, create it with write_app_runnable first

Example fix

// before
write_app_runnable({ path: 'f/app_main', key: 'processData', ... }) // no such key
// after
// error says: Available runnables: process, fetcher
write_app_runnable({ path: 'f/app_main', key: 'process', ... })
Defensive patterns

Strategy: validation

Validate before calling

const { value } = await loadAppDraftValue(path, workspace)
if (!(key in (value.runnables ?? {}))) {
  console.warn(`Runnable "${key}" missing; available:`, Object.keys(value.runnables ?? {}))
}

Type guard

function runnableExists(runnables: Record<string, unknown> | undefined, key: string): boolean {
  return !!runnables && key in runnables
}

Try / catch

try {
  await writeAppRunnable(args)
} catch (e) {
  const m = /Available runnables: (.+)\./.exec(e instanceof Error ? e.message : '')
  if (m) {
    // retry with one of m[1].split(', ') or create the runnable first
  }
}

Prevention

When it happens

Trigger: A runnable-targeting tool (e.g. write_app_runnable/read of a runnable) is called with `key` not present in `value.runnables`, such as a typo'd key or one from a stale schema snapshot.

Common situations: Model invents a runnable name instead of listing available ones; runnable was renamed or deleted earlier in the session; model confuses file paths with runnable keys.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at frontend/src/lib/components/copilot/chat/global/core.ts:5986

}

/**
 * Runs one backend runnable through `execute_component` in preview mode, the way the editor
 * preview does: inline executes draft code, a path runnable the deployed item it names.
 * Without it the chat can only wire an app up and hope.
 */
async function testRunAppRunnable(
	args: z.infer<typeof testRunAppRunnableSchema>,
	ctx: WriteDraftCtx
): Promise<string> {
	const { workspace, toolId, toolCallbacks } = ctx
	const { path, key } = args

	const { value } = await loadAppDraftValue(path, workspace)
	const runnable = value.runnables?.[key] as PersistedRunnable | undefined
	if (!runnable) {
		const known = Object.keys(value.runnables ?? {})
		throw new Error(
			`App "${path}" has no backend runnable "${key}".` +
				(known.length ? ` Available runnables: ${known.join(', ')}.` : '')
		)
	}

	// Copied, not aliased: the ctx pass below writes into it.
	const testArgs = { ...normalizeTestRunArgs(args.args) }
	// Setting force_viewer_static_fields is what puts execute_component in preview
	// mode (apps.rs `is_preview`), which is what makes inline draft code run at all.
	// It must be sent even when the runnable has no static fields.
	const staticFields = Object.fromEntries(
		Object.entries(runnable.fields ?? {})
			.filter(([, field]) => field?.type === 'static')
			.map(([name, field]) => [name, field?.value])
	)
	// A ctx-bound input is filled by the server from `$ctx:<prop>`, exactly as
	// RawAppBackgroundRunner does before executing. Without this the argument arrives
	// missing and the runnable fails for a reason that has nothing to do with its code.

View on GitHub (pinned to e474e8803c)