windmill-labs/windmill · error

App "${path}" has no backend runnable "${key}". Available ru

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.

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)

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.