{"record":{"id":"031ecf5a39b103f8","repo":"stablyai/orca","slug":"content-is-required","errorCode":null,"errorMessage":"content is required","messagePattern":"content is required","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ipc/filesystem.ts","lineNumber":692,"sourceCode":"          await cleanupLocalTransferPath(tempPath)\n        }\n      }\n    }\n  )\n\n  registerFilesystemDownloadFolderHandlers()\n\n  ipcMain.handle(\n    'fs:saveDownloadedFile',\n    async (\n      event,\n      args: { suggestedName?: string; content?: string; encoding?: 'utf8' | 'base64' }\n    ): Promise<DownloadFileResult> => {\n      const suggestedName = sanitizeLocalDownloadFilename(\n        validateRequiredString(args?.suggestedName, 'suggestedName')\n      )\n      if (typeof args?.content !== 'string') {\n        throw new Error('content is required')\n      }\n      const content = args.content\n      const encoding = args?.encoding === 'base64' ? 'base64' : 'utf8'\n      const parentWindow = BrowserWindow.fromWebContents(event.sender) ?? undefined\n      const dialogResult = parentWindow\n        ? await dialog.showSaveDialog(parentWindow, { defaultPath: suggestedName })\n        : await dialog.showSaveDialog({ defaultPath: suggestedName })\n      if (dialogResult.canceled || !dialogResult.filePath) {\n        return { canceled: true }\n      }\n\n      const destinationPath = dialogResult.filePath\n      const { existed } = await inspectDownloadDestination(destinationPath)\n      const tempPath = createSiblingTransferPath(destinationPath, 'download')\n      let promoted = false\n      try {\n        await writeFile(tempPath, decodeDownloadedFileContent(content, encoding))\n        await promoteDownloadedFile(tempPath, destinationPath, existed)","sourceCodeStart":674,"sourceCodeEnd":710,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/src/main/ipc/filesystem.ts#L674-L710","documentation":"Thrown by the 'fs:saveDownloadedFile' handler (src/main/ipc/filesystem.ts:692) when args.content is not a string. This handler is the 'save already-fetched content' path (distinct from the streaming start/append/finish flow); the contract requires content be passed as a utf8 or base64 string. Non-string payloads are rejected at the IPC boundary before any disk write.","triggerScenarios":"Calling ipcRenderer.invoke('fs:saveDownloadedFile', { suggestedName, content }) with content omitted, undefined, null, a number, or a binary buffer/TypedArray instead of a base64 string. The `typeof args?.content !== 'string'` guard fires before sanitizeLocalDownloadFilename is reached again.","commonSituations":"Renderer refactor that stopped threading content through; a binary file saved without setting encoding:'base64'; a code path passing a Uint8Array/Buffer directly; an event payload that was JSON-round-tripped and dropped an undefined field.","solutions":["Pass content as a string, with encoding:'base64' for binary data, in the invoke payload.","For large or streaming files, switch to fs:startDownloadedFile + fs:appendDownloadedFileChunk + fs:finishDownloadedFile instead of fs:saveDownloadedFile.","Add a renderer-side type check on the payload so the error surfaces at the call site, not over IPC."],"exampleFix":"// before: content missing\nawait invoke('fs:saveDownloadedFile', { suggestedName: 'log.txt' })\n\n// after: content provided, base64 for binary\nawait invoke('fs:saveDownloadedFile', {\n  suggestedName: 'logo.png',\n  content: bytes.toString('base64'),\n  encoding: 'base64'\n})","handlingStrategy":"validation","validationCode":"function isValidSaveArgs(a: unknown): a is { suggestedName: string; content: string; encoding?: 'utf8' | 'base64' } {\n  return typeof (a as any)?.suggestedName === 'string'\n    && typeof (a as any)?.content === 'string'\n}","typeGuard":"const isStringContent = (a: unknown): a is { content: string } =>\n  typeof (a as { content?: unknown })?.content === 'string'","tryCatchPattern":null,"preventionTips":["Type the invoke payload with the shared IPC types so missing content fails at compile time.","For binary, set encoding:'base64' and pass a base64 string, never a Buffer/TypedArray.","Use the streaming start/append/finish flow for large files instead of saveDownloadedFile."],"tags":["validation","ipc","filesystem","typescript"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}