{"record":{"id":"08b50d0a45302f3e","repo":"windmill-labs/windmill","slug":"target-path-does-not-match-runnable-target","errorCode":null,"errorMessage":"'${target.path}' does not match runnable '${target.key}' language. Use backend/${target.key}/main.${expectedExtension}.","messagePattern":"'(.+?)' does not match runnable '(.+?)' language\\. Use backend/(.+?)/main\\.(.+?)\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/app/core.ts","lineNumber":631,"sourceCode":"\t\t\t\tconst frontendContent = helpers.getFrontendFile(target.path)\n\t\t\t\tif (frontendContent === undefined) {\n\t\t\t\t\tthrow new Error(`Frontend file '${target.path}' not found.`)\n\t\t\t\t}\n\t\t\t\tcurrentContent = frontendContent\n\t\t\t} else {\n\t\t\t\tbackendRunnable = helpers.getBackendRunnable(target.key)\n\t\t\t\tif (!backendRunnable) {\n\t\t\t\t\tthrow new Error(`Backend runnable '${target.key}' not found.`)\n\t\t\t\t}\n\t\t\t\tif (backendRunnable.type !== 'inline' || !backendRunnable.inlineScript) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`'${target.path}' points to backend runnable '${target.key}', but only inline runnables can be patched as files.`\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tconst expectedExtension = getBackendInlineScriptExtension(backendRunnable)\n\t\t\t\tif (target.extension !== expectedExtension) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`'${target.path}' does not match runnable '${target.key}' language. Use backend/${target.key}/main.${expectedExtension}.`\n\t\t\t\t\t)\n\t\t\t\t}\n\n\t\t\t\tcurrentContent = backendRunnable.inlineScript.content ?? ''\n\t\t\t}\n\n\t\t\tconst updatedContent = findAndReplace(\n\t\t\t\tcurrentContent,\n\t\t\t\toldString,\n\t\t\t\tnewString,\n\t\t\t\treplaceAll,\n\t\t\t\t'current file content'\n\t\t\t)\n\n\t\t\ttoolCallbacks.setToolStatus(toolId, {\n\t\t\t\tcontent: `Patching '${target.path}'...`\n\t\t\t})","sourceCodeStart":613,"sourceCodeEnd":649,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/app/core.ts#L613-L649","documentation":"For inline backend runnables, applyPatch enforces that the patch path's extension matches the runnable's script language: TypeScript runnables use main.ts, Python (python3) runnables use main.py (getBackendInlineScriptExtension). This error is thrown when the extension in the path disagrees with the runnable's actual language.","triggerScenarios":"Patching 'backend/step/main.py' when the runnable's inlineScript.language is not python3 (defaults to ts), or patching 'main.ts' for a Python runnable. resolveAppPatchTarget only matches .ts/.py paths, but either can be chosen regardless of the runnable's real language.","commonSituations":"Model assuming Python for a TS step; a runnable whose language was changed after the model read an older file listing; generated paths defaulting to .ts for Python-heavy apps.","solutions":["Use the extension matching the runnable's language: backend/<key>/main.ts for TypeScript, backend/<key>/main.py for python3","Check inlineScript.language on the runnable before constructing the path","If the language itself is wrong, change the runnable's language through the app definition rather than patching a mismatched file"],"exampleFix":"// before\napplyPatch({ path: 'backend/etl/main.ts', ... }) // runnable.language = python3\n// after\napplyPatch({ path: 'backend/etl/main.py', ... })","handlingStrategy":"validation","validationCode":"const expected = runnable.inlineScript?.language === 'python3' ? 'py' : 'ts'\nif (!path.endsWith(`main.${expected}`)) {\n  throw new Error(`Use backend/${key}/main.${expected} for this runnable`)\n}","typeGuard":"function pathMatchesRunnableLanguage(path: string, r: BackendRunnable): boolean {\n  const expected = r.inlineScript?.language === 'python3' ? 'py' : 'ts'\n  return path.endsWith(`main.${expected}`)\n}","tryCatchPattern":"try {\n  await patchTool({ path, ... })\n} catch (e) {\n  const m = e instanceof Error && e.message.match(/Use (backend\\/.*)\\./)\n  if (m) { return patchTool({ path: m[1], ... }) } // retry with corrected extension\n  throw e\n}","preventionTips":["Read inlineScript.language before constructing the patch path","Default to .ts only when the language is confirmed TypeScript","Regenerate file listings after any language change to a runnable"],"tags":["copilot","app-editor","path-validation"],"backgroundTag":"schema-validation-failed","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"}