{"record":{"id":"8723c82370cb8517","repo":"windmill-labs/windmill","slug":"app-path-has-no-backend-runnable-key-av","errorCode":null,"errorMessage":"App \"${path}\" has no backend runnable \"${key}\". Available runnables: ${known.join(', ')}.","messagePattern":"App \"(.+?)\" has no backend runnable \"(.+?)\"\\. Available runnables: (.+?)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/global/core.ts","lineNumber":5986,"sourceCode":"}\n\n/**\n * Runs one backend runnable through `execute_component` in preview mode, the way the editor\n * preview does: inline executes draft code, a path runnable the deployed item it names.\n * Without it the chat can only wire an app up and hope.\n */\nasync function testRunAppRunnable(\n\targs: z.infer<typeof testRunAppRunnableSchema>,\n\tctx: WriteDraftCtx\n): Promise<string> {\n\tconst { workspace, toolId, toolCallbacks } = ctx\n\tconst { path, key } = args\n\n\tconst { value } = await loadAppDraftValue(path, workspace)\n\tconst runnable = value.runnables?.[key] as PersistedRunnable | undefined\n\tif (!runnable) {\n\t\tconst known = Object.keys(value.runnables ?? {})\n\t\tthrow new Error(\n\t\t\t`App \"${path}\" has no backend runnable \"${key}\".` +\n\t\t\t\t(known.length ? ` Available runnables: ${known.join(', ')}.` : '')\n\t\t)\n\t}\n\n\t// Copied, not aliased: the ctx pass below writes into it.\n\tconst testArgs = { ...normalizeTestRunArgs(args.args) }\n\t// Setting force_viewer_static_fields is what puts execute_component in preview\n\t// mode (apps.rs `is_preview`), which is what makes inline draft code run at all.\n\t// It must be sent even when the runnable has no static fields.\n\tconst staticFields = Object.fromEntries(\n\t\tObject.entries(runnable.fields ?? {})\n\t\t\t.filter(([, field]) => field?.type === 'static')\n\t\t\t.map(([name, field]) => [name, field?.value])\n\t)\n\t// A ctx-bound input is filled by the server from `$ctx:<prop>`, exactly as\n\t// RawAppBackgroundRunner does before executing. Without this the argument arrives\n\t// missing and the runnable fails for a reason that has nothing to do with its code.","sourceCodeStart":5968,"sourceCodeEnd":6004,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/global/core.ts#L5968-L6004","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Retry with one of the keys listed in the error's 'Available runnables' section","Re-read the app draft to get the current runnables map and pick the correct key","If the runnable should exist, create it with write_app_runnable first"],"exampleFix":"// before\nwrite_app_runnable({ path: 'f/app_main', key: 'processData', ... }) // no such key\n// after\n// error says: Available runnables: process, fetcher\nwrite_app_runnable({ path: 'f/app_main', key: 'process', ... })","handlingStrategy":"validation","validationCode":"const { value } = await loadAppDraftValue(path, workspace)\nif (!(key in (value.runnables ?? {}))) {\n  console.warn(`Runnable \"${key}\" missing; available:`, Object.keys(value.runnables ?? {}))\n}","typeGuard":"function runnableExists(runnables: Record<string, unknown> | undefined, key: string): boolean {\n  return !!runnables && key in runnables\n}","tryCatchPattern":"try {\n  await writeAppRunnable(args)\n} catch (e) {\n  const m = /Available runnables: (.+)\\./.exec(e instanceof Error ? e.message : '')\n  if (m) {\n    // retry with one of m[1].split(', ') or create the runnable first\n  }\n}","preventionTips":["Parse the 'Available runnables' hint from the error to self-correct","Re-read the app draft after any rename/delete of runnables","Never guess runnable keys — enumerate them first"],"tags":["ai-agent","not-found","app-editing"],"backgroundTag":"resource-not-found","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"}