{"record":{"id":"49835125bba8219e","repo":"windmill-labs/windmill","slug":"frontend-file-target-path-not-found","errorCode":null,"errorMessage":"Frontend file '${target.path}' not found.","messagePattern":"Frontend file '(.+?)' not found\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/app/core.ts","lineNumber":615,"sourceCode":"\t\tshowDetails: true,\n\t\tshowFade: true,\n\t\tfn: async ({ args, helpers, toolId, toolCallbacks }) => {\n\t\t\tconst parsedArgs = getPatchFileSchema().parse(args)\n\t\t\tconst { old_string: oldString, new_string: newString, replace_all: replaceAll } = parsedArgs\n\t\t\tconst target = resolveAppPatchTarget(parsedArgs.path)\n\t\t\tlet currentContent = ''\n\t\t\tlet backendRunnable: BackendRunnable | undefined\n\n\t\t\tif (target.type === 'frontend') {\n\t\t\t\tif (target.path === '/wmill.d.ts') {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\"'/wmill.d.ts' is generated automatically. Edit backend runnables instead.\"\n\t\t\t\t\t)\n\t\t\t\t}\n\n\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)","sourceCodeStart":597,"sourceCodeEnd":633,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/app/core.ts#L597-L633","documentation":"The applyPatch tool in the app-edit copilot resolves the given path to a frontend file and fetches its current content via helpers.getFrontendFile. When the path is not a backend runnable path and no frontend file exists at that path, this error is thrown. It signals a bad patch target: the file the model wants to edit does not exist in the app.","triggerScenarios":"Calling the patch tool with parsedArgs.path that maps to type 'frontend' (anything not matching /^backend\\/([^/]+)\\/main\\.(ts|py)$/) while getFrontendFile returns undefined — path typos, wrong extension, or a file that was never created.","commonSituations":"Model hallucinating a file path ('/src/App.tsx' when the app uses '/index.tsx'); deleting a file in an earlier step then patching it; case-sensitive path mismatches; patching before creating the file.","solutions":["Call the file-listing/read tool first to confirm the exact existing path, then patch that path","Create the file with the create-file tool before patching it","Check for extension mismatches (e.g. .tsx vs .ts) and leading-slash normalization — resolveAppPatchTarget adds '/' if missing","If the file was intentionally new, use the creation path instead of patch"],"exampleFix":"// before\nawait applyPatch({ path: '/src/App.tsx', ... })\n// after\nconst files = await listFiles()\nawait applyPatch({ path: files.find(f => f.endsWith('.tsx'))?.path, ... })","handlingStrategy":"validation","validationCode":"const existing = helpers.getFrontendFile(normalizedPath)\nif (existing === undefined) throw new Error(`Refusing to patch: no frontend file at ${normalizedPath}`)","typeGuard":"function frontendFileExists(path: string, helpers: AppHelpers): boolean {\n  return helpers.getFrontendFile(path.startsWith('/') ? path : '/' + path) !== undefined\n}","tryCatchPattern":"try {\n  await patchTool({ path, ... })\n} catch (e) {\n  if (e instanceof Error && /^Frontend file '.*' not found/.test(e.message)) {\n    await createFileTool({ path, content: '' }) // then retry patch\n    return\n  }\n  throw e\n}","preventionTips":["List files (read tool) before patching; never patch from memory of an assumed path","Create new files with the create tool, patch only existing ones","Normalize leading slashes and check extension spelling (.tsx vs .ts)"],"tags":["copilot","app-editor","file-not-found"],"backgroundTag":"file-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"}