windmill-labs/windmill · error

Frontend file '${target.path}' not found.

Error message

Frontend file '${target.path}' not found.

What it means

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.

Source

Thrown at frontend/src/lib/components/copilot/chat/app/core.ts:615

		showDetails: true,
		showFade: true,
		fn: async ({ args, helpers, toolId, toolCallbacks }) => {
			const parsedArgs = getPatchFileSchema().parse(args)
			const { old_string: oldString, new_string: newString, replace_all: replaceAll } = parsedArgs
			const target = resolveAppPatchTarget(parsedArgs.path)
			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}.`
					)

View on GitHub (pinned to e474e8803c)

Solutions

  1. Call the file-listing/read tool first to confirm the exact existing path, then patch that path
  2. Create the file with the create-file tool before patching it
  3. Check for extension mismatches (e.g. .tsx vs .ts) and leading-slash normalization — resolveAppPatchTarget adds '/' if missing
  4. If the file was intentionally new, use the creation path instead of patch

Example fix

// before
await applyPatch({ path: '/src/App.tsx', ... })
// after
const files = await listFiles()
await applyPatch({ path: files.find(f => f.endsWith('.tsx'))?.path, ... })
Defensive patterns

Strategy: validation

Validate before calling

const existing = helpers.getFrontendFile(normalizedPath)
if (existing === undefined) throw new Error(`Refusing to patch: no frontend file at ${normalizedPath}`)

Type guard

function frontendFileExists(path: string, helpers: AppHelpers): boolean {
  return helpers.getFrontendFile(path.startsWith('/') ? path : '/' + path) !== undefined
}

Try / catch

try {
  await patchTool({ path, ... })
} catch (e) {
  if (e instanceof Error && /^Frontend file '.*' not found/.test(e.message)) {
    await createFileTool({ path, content: '' }) // then retry patch
    return
  }
  throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

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


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/49835125bba8219e. Report an issue: GitHub.