{"record":{"id":"4806045170a8c33a","repo":"windmill-labs/windmill","slug":"delete-app-file-only-deletes-frontend-files-use-d","errorCode":null,"errorMessage":"delete_app_file only deletes frontend files. Use delete_app_runnable for backend runnables.","messagePattern":"delete_app_file only deletes frontend files\\. Use delete_app_runnable for backend runnables\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/global/core.ts","lineNumber":5834,"sourceCode":"\t})\n\n\tconst { value } = await loadAppDraftValue(args.path, workspace)\n\tvalue.files = { ...value.files, [target.filePath]: args.content }\n\tconst result = await saveAppDraft(workspace, args.path, value)\n\treturn finishAppDraftWrite(result, ctx, () => ({\n\t\tcontent: `Updated ${target.filePath} in app \"${args.path}\"`,\n\t\tmessage: `Updated draft app \"${args.path}\" with frontend file \"${target.filePath}\".`\n\t}))\n}\n\nasync function deleteAppFile(\n\targs: { path: string; file_path: string },\n\tctx: WriteDraftCtx\n): Promise<string> {\n\tconst { workspace, toolId, toolCallbacks } = ctx\n\tconst target = resolveAppFileTarget(args.file_path)\n\tif (target.kind !== 'frontend') {\n\t\tthrow new Error(\n\t\t\t`delete_app_file only deletes frontend files. Use delete_app_runnable for backend runnables.`\n\t\t)\n\t}\n\tassertNotGeneratedAppFile(target.filePath)\n\n\ttoolCallbacks.setToolStatus(toolId, {\n\t\tcontent: `Deleting ${target.filePath} from app \"${args.path}\"...`\n\t})\n\n\tconst { value } = await loadAppDraftValue(args.path, workspace)\n\tif (!(target.filePath in value.files)) {\n\t\tthrow new Error(`Frontend file \"${target.filePath}\" not found in app \"${args.path}\".`)\n\t}\n\tconst { [target.filePath]: _removed, ...remaining } = value.files\n\tvalue.files = remaining\n\tconst result = await saveAppDraft(workspace, args.path, value)\n\treturn finishAppDraftWrite(result, ctx, () => ({\n\t\tcontent: `Removed ${target.filePath} from app \"${args.path}\"`,","sourceCodeStart":5816,"sourceCodeEnd":5852,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/global/core.ts#L5816-L5852","documentation":"The delete_app_file copilot tool only removes entries from the app's frontend files map. When the given file_path resolves to a backend runnable, it throws and points at delete_app_runnable, since runnables are stored in a separate map with their own lifecycle.","triggerScenarios":"The AI model calls delete_app_file with a `file_path` that resolveAppFileTarget classifies as a backend runnable rather than a frontend file.","commonSituations":"Model tries to clean up by deleting what it thinks is a file but is actually an inline backend script; stale app schema in the model's context causes it to mistake runnables for files.","solutions":["Call delete_app_runnable with the runnable key instead","Re-read the app to list actual frontend files before deleting","Refresh the model's context with the current app schema"],"exampleFix":"// before\ndelete_app_file({ path: 'f/app_main', file_path: 'backend/legacy.py' })\n// after\ndelete_app_runnable({ path: 'f/app_main', key: 'legacy' })","handlingStrategy":"validation","validationCode":"const target = resolveAppFileTarget(args.file_path)\nif (target.kind !== 'frontend') {\n  // route to delete_app_runnable instead\n}","typeGuard":"function isFrontendTarget(t: { kind: string }): t is { kind: 'frontend'; filePath: string } {\n  return t.kind === 'frontend'\n}","tryCatchPattern":"try {\n  await deleteAppFile(args)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('delete_app_runnable')) {\n    await deleteAppRunnable({ path: args.path, key: args.file_path })\n  }\n}","preventionTips":["Classify the target before choosing the delete tool","Refresh the app listing after renames/deletes so the model doesn't target stale entries"],"tags":["ai-agent","tool-arguments","app-editing"],"backgroundTag":"wrong-tool-for-target","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"}