{"record":{"id":"afc0602b6f72cae4","repo":"windmill-labs/windmill","slug":"runnable-target-key-language-is-expected","errorCode":null,"errorMessage":"Runnable \"${target.key}\" language is ${expected}. Use backend/${target.key}/main.${expected}.","messagePattern":"Runnable \"(.+?)\" language is (.+?)\\. Use backend/(.+?)/main\\.(.+?)\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/global/core.ts","lineNumber":1781,"sourceCode":" * with a clear message otherwise.\n */\nfunction getInlineRunnableContent(\n\tvalue: AppDraftValue,\n\ttarget: { kind: 'backend'; filePath: string; key: string; extension: 'ts' | 'py' },\n\tappPath: string\n): { content: string; runnable: PersistedRunnable } {\n\tconst runnable = value.runnables[target.key] as PersistedRunnable | undefined\n\tif (!runnable) {\n\t\tthrow new Error(`Backend runnable \"${target.key}\" not found in app \"${appPath}\".`)\n\t}\n\tif (runnable.type !== 'inline' && runnable.type !== 'runnableByName') {\n\t\tthrow new Error(\n\t\t\t`Runnable \"${target.key}\" is not inline. Use read_workspace_item on the referenced ${runnable.runType ?? 'item'} instead.`\n\t\t)\n\t}\n\tconst expected = getInlineScriptExtension(runnable)\n\tif (target.extension !== expected) {\n\t\tthrow new Error(\n\t\t\t`Runnable \"${target.key}\" language is ${expected}. Use backend/${target.key}/main.${expected}.`\n\t\t)\n\t}\n\treturn { content: runnable.inlineScript?.content ?? '', runnable }\n}\n\nasync function loadAppValueForRead(path: string, workspace: string): Promise<AppDraftValue> {\n\tconst draft = await getGlobalDraft(workspace, 'app', path)\n\tif (draft && draft.value && typeof draft.value === 'object' && 'files' in draft.value) {\n\t\treturn draft.value as AppDraftValue\n\t}\n\n\tconst app = await AppService.getAppByPath({ workspace, path })\n\treturn appSourceToDraftValue(app, app)\n}\n\nasync function loadAppDraftValue(path: string, workspace: string): Promise<LoadedAppDraftValue> {\n\tconst draft = await getGlobalDraft(workspace, 'app', path)","sourceCodeStart":1763,"sourceCodeEnd":1799,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/global/core.ts#L1763-L1799","documentation":"Each inline runnable has a language derived from its stored inline script (via getInlineScriptExtension), and the tool target must supply a matching file extension. This error fires when the target's extension does not match the runnable's actual language, so file paths like backend/<key>/main.ts vs main.py must match.","triggerScenarios":"A tool call provides target.extension that differs from getInlineScriptExtension(runnable), e.g. writing backend/foo/main.py when the inline script is TypeScript.","commonSituations":"The model guesses the wrong language for an inline script; the runnable was re-authored in a different language than the model assumes.","solutions":["Check the runnable's inlineScript language and use the corresponding extension (e.g. main.ts, main.py)","Retry the tool call with backend/<key>/main.<expected-extension>"],"exampleFix":"// before\nrunBackendFile('backend/myStep/main.py', code)\n// after\nrunBackendFile('backend/myStep/main.ts', code) // matches the inline script's TypeScript","handlingStrategy":"validation","validationCode":"const expected = getInlineScriptExtension(runnable);\nif (target.extension !== expected) throw new Error(`use main.${expected}`);","typeGuard":"function matchesExtension(t, runnable) { return t.extension === getInlineScriptExtension(runnable); }","tryCatchPattern":"try { writeFile(path, code) } catch (e) { if (e.message.includes('language is')) retryWithExtension(e.message.match(/main\\.(\\w+)/)?.[1]); }","preventionTips":["Derive the extension from the runnable, not from guesswork","Always use backend/<key>/main.<ext> path convention"],"tags":["ai-copilot","file-extension","language-mismatch"],"backgroundTag":"file-extension-mismatch","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"}