windmill-labs/windmill · error
Backend runnable '${target.key}' not found.
Error message
Backend runnable '${target.key}' not found. What it means
When the patch path targets a backend runnable (backend/<key>/main.ts|py), applyPatch looks the runnable up by key via helpers.getBackendRunnable. This error is thrown when no runnable with that key exists in the app's frontend definition. It catches references to deleted, renamed, or never-existing backend runnables.
Source
Thrown at frontend/src/lib/components/copilot/chat/app/core.ts:621
let currentContent = ''
let backendRunnable: BackendRunnable | undefined
if (target.type === 'frontend') {
if (target.path === '/wmill.d.ts') {
throw new Error(
"'/wmill.d.ts' is generated automatically. Edit backend runnables instead."
)
}
const frontendContent = helpers.getFrontendFile(target.path)
if (frontendContent === undefined) {
throw new Error(`Frontend file '${target.path}' not found.`)
}
currentContent = frontendContent
} else {
backendRunnable = helpers.getBackendRunnable(target.key)
if (!backendRunnable) {
throw new Error(`Backend runnable '${target.key}' not found.`)
}
if (backendRunnable.type !== 'inline' || !backendRunnable.inlineScript) {
throw new Error(
`'${target.path}' points to backend runnable '${target.key}', but only inline runnables can be patched as files.`
)
}
const expectedExtension = getBackendInlineScriptExtension(backendRunnable)
if (target.extension !== expectedExtension) {
throw new Error(
`'${target.path}' does not match runnable '${target.key}' language. Use backend/${target.key}/main.${expectedExtension}.`
)
}
currentContent = backendRunnable.inlineScript.content ?? ''
}
const updatedContent = findAndReplace(View on GitHub (pinned to e474e8803c)
Solutions
- List the app's backend runnables first and patch an existing key
- Re-create the runnable (via the add-runnable tool) before patching its file
- Verify the key segment between backend/ and /main — it must exactly equal the runnable id in the app definition
Defensive patterns
Strategy: validation
Validate before calling
const runnable = helpers.getBackendRunnable(key)
if (!runnable) throw new Error(`No backend runnable named ${key}`) Type guard
function backendRunnableExists(key: string, helpers: AppHelpers): boolean {
return helpers.getBackendRunnable(key) !== undefined
} Try / catch
try {
await patchTool({ path: `backend/${key}/main.ts`, ... })
} catch (e) {
if (e instanceof Error && e.message.startsWith('Backend runnable')) {
toolCallbacks.report(`Runnable '${key}' does not exist; list runnables first`)
return
}
throw e
} Prevention
- Enumerate the app's runnables before constructing backend/<key>/main.* paths
- Never guess runnable keys — take them from the app definition or a prior listing
- Account for renames/deletions from earlier steps in the same session
When it happens
Trigger: Patching 'backend/my_step/main.ts' when the app's runnables map has no 'my_step' key — the runnable was renamed, removed by a previous patch, or the model invented the key.
Common situations: Model guessing runnable names instead of listing them; earlier diff removed the runnable; key casing/spelling mismatch; editing a flow-generated app where steps use different ids.
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Frontend file '${target.path}' not found.
- '/wmill.d.ts' is generated automatically. Edit backend runna
- '${target.path}' points to backend runnable '${target.key}',
- '${target.path}' does not match runnable '${target.key}' lan
- File not found: ${filePath}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/331bd578403221d5.
Report an issue: GitHub.