windmill-labs/windmill · error

'${target.path}' does not match runnable '${target.key}' lan

Error message

'${target.path}' does not match runnable '${target.key}' language. Use backend/${target.key}/main.${expectedExtension}.

What it means

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.

Source

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

				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(
				currentContent,
				oldString,
				newString,
				replaceAll,
				'current file content'
			)

			toolCallbacks.setToolStatus(toolId, {
				content: `Patching '${target.path}'...`
			})

View on GitHub (pinned to e474e8803c)

Solutions

  1. Use the extension matching the runnable's language: backend/<key>/main.ts for TypeScript, backend/<key>/main.py for python3
  2. Check inlineScript.language on the runnable before constructing the path
  3. If the language itself is wrong, change the runnable's language through the app definition rather than patching a mismatched file

Example fix

// before
applyPatch({ path: 'backend/etl/main.ts', ... }) // runnable.language = python3
// after
applyPatch({ path: 'backend/etl/main.py', ... })
Defensive patterns

Strategy: validation

Validate before calling

const expected = runnable.inlineScript?.language === 'python3' ? 'py' : 'ts'
if (!path.endsWith(`main.${expected}`)) {
  throw new Error(`Use backend/${key}/main.${expected} for this runnable`)
}

Type guard

function pathMatchesRunnableLanguage(path: string, r: BackendRunnable): boolean {
  const expected = r.inlineScript?.language === 'python3' ? 'py' : 'ts'
  return path.endsWith(`main.${expected}`)
}

Try / catch

try {
  await patchTool({ path, ... })
} catch (e) {
  const m = e instanceof Error && e.message.match(/Use (backend\/.*)\./)
  if (m) { return patchTool({ path: m[1], ... }) } // retry with corrected extension
  throw e
}

Prevention

When it happens

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

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

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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