{"record":{"id":"23d0999a860d6619","repo":"windmill-labs/windmill","slug":"file-only-applies-to-multi-file-apps-entry-kind","errorCode":null,"errorMessage":"file only applies to multi-file apps; ${entry.kind} \"${path}\" diffs as a single document — call again without file.","messagePattern":"file only applies to multi-file apps; (.+?) \"(.+?)\" diffs as a single document — call again without file\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/global/core.ts","lineNumber":7041,"sourceCode":"\tconst changedFileCount = entry.files ? Object.keys(entry.files).length : 0\n\tif (entry.status === 'unchanged' || (!entry.patch && changedFileCount === 0)) {\n\t\t// A masked value can differ in content without producing a patch —\n\t\t// never report that as \"same content\".\n\t\tconst message = entry.valueMasked\n\t\t\t? `${entry.kind} \"${path}\": no visible config differences vs parent \"${parent}\", but variable values are never shown in chat, so a value change cannot be displayed. The workspace comparison reports it as ${entry.ahead > 0 || entry.behind > 0 ? `differing (ahead ${entry.ahead}, behind ${entry.behind})` : 'in sync'}.`\n\t\t\t: entry.kind === 'folder'\n\t\t\t\t? `folder \"${path}\": no comparable differences vs parent \"${parent}\" — the folder display name is not exposed by the API and may be what differs (comparison reports ahead ${entry.ahead}, behind ${entry.behind}).`\n\t\t\t\t: `${entry.kind} \"${path}\" has the same content in the fork and its parent \"${parent}\" (only version history differs).`\n\t\treturn draftCaveat + message\n\t}\n\tconst header =\n\t\tentry.status === 'only_in_fork'\n\t\t\t? `${entry.kind} \"${path}\" exists only in the fork — not in parent \"${parent}\". Full content:\\n\\n`\n\t\t\t: entry.status === 'only_in_parent'\n\t\t\t\t? `${entry.kind} \"${path}\" exists only in parent \"${parent}\" — not in the fork. Parent content:\\n\\n`\n\t\t\t\t: `Fork changes vs parent \"${parent}\" for ${entry.kind} \"${path}\":\\n\\n`\n\tif (args.file !== undefined && !entry.files) {\n\t\tthrow new Error(\n\t\t\t`file only applies to multi-file apps; ${entry.kind} \"${path}\" diffs as a single document — call again without file.`\n\t\t)\n\t}\n\tconst body = entry.files\n\t\t? renderEntryFiles(entry.files, entry.patch ?? '', args)\n\t\t: windowPatchBody(entry.patch ?? '', args.offset ?? 0, args.limit ?? DIFF_READ_DEFAULT_LINES)\n\treturn draftCaveat + header + body\n}\n\nconst DIFF_SEARCH_DEFAULT_MAX_MATCHES = 50\nconst DIFF_SEARCH_MAX_MATCHES_CEILING = 200\n\ninterface DiffSearchUnit {\n\t/** Item path, or `${itemPath}/${fileName}` for a file inside an app. */\n\tsubject: string\n\tpatch: string\n}\n","sourceCodeStart":7023,"sourceCodeEnd":7059,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/global/core.ts#L7023-L7059","documentation":"Mirror of error 412 for the fork-comparison path: the `file` argument only applies to multi-file apps. When the fork diff entry has no `files` map (single-document kind, or only_in_fork/only_in_parent content dumps without file granularity), passing `file` throws this corrective error telling the caller to retry without it.","triggerScenarios":"Calling the fork diff tool with `args.file` set while `entry.files` is undefined — e.g. diffing a script or a flow against the parent, or an only_in_fork item whose full content is returned as a single document.","commonSituations":"Agents reusing the `file` argument across calls after diffing an app; assuming parent-side apps always expose file granularity (older comparison data may not include files).","solutions":["Retry without the `file` argument","For multi-file apps, verify the entry exposes files (type 'app'/'raw_app' with a computed comparison) before narrowing"],"exampleFix":"// before\ndiffFork({ type: 'script', path: 'f/build', file: 'main.ts' })\n// after\ndiffFork({ type: 'script', path: 'f/build' })","handlingStrategy":"validation","validationCode":"if (args.file !== undefined && entry.files === undefined) {\n  // single-document fork diff: drop file before calling\n  delete args.file\n}","typeGuard":"function entryHasFiles(entry: { files?: Record<string, unknown> }): boolean {\n  return entry.files !== undefined\n}","tryCatchPattern":"try {\n  return await diffFork(args)\n} catch (e) {\n  if (String(e?.message).startsWith('file only applies to multi-file apps')) {\n    return await diffFork({ ...args, file: undefined })\n  }\n  throw e\n}","preventionTips":["Only pass `file` when the fork entry exposes a files map","Drop `file` on retry after this error","Remember only_in_fork/only_in_parent entries are single-document dumps"],"tags":["arguments","validation","forks"],"backgroundTag":"invalid-tool-arguments","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"}