{"record":{"id":"6be27813670cf94e","repo":"gitbutlerapp/gitbutler","slug":"toolarge-name-is-toolarge-size-1024-1024-tofixed-1-mb-over","errorCode":null,"errorMessage":"${tooLarge.name} is ${(tooLarge.size / (1024 * 1024)).toFixed(1)} MB, over the ${UPLOAD_SIZE_LIMIT / (1024 * 1024)} MB upload limit","messagePattern":"(.+?) is (.+?) MB, over the (.+?) MB upload limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/lite/ui/src/api/mutations.ts","lineNumber":304,"sourceCode":"\t\t\treturn splitGeneratedDescription(response);\n\t\t},\n\t\tmeta: { failureTitle: \"Failed to generate description\" },\n\t});\n};\n\n/**\n * Upload files and return them in the order given, so the markdown they turn\n * into matches the order they were picked or dropped in.\n *\n * One failure fails the batch: a body half-linking a set of screenshots is\n * worse than one the user retries.\n */\nexport const useUploadFiles = () =>\n\tuseMutation({\n\t\tmutationFn: async (files: Array<File>) => {\n\t\t\tconst tooLarge = oversizedFile(files);\n\t\t\tif (tooLarge !== undefined) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${tooLarge.name} is ${(tooLarge.size / (1024 * 1024)).toFixed(1)} MB, over the ${\n\t\t\t\t\t\tUPLOAD_SIZE_LIMIT / (1024 * 1024)\n\t\t\t\t\t} MB upload limit`,\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn Promise.all(\n\t\t\t\tfiles.map(async (file) =>\n\t\t\t\t\twindow.lite.uploadFile({\n\t\t\t\t\t\tfilename: file.name,\n\t\t\t\t\t\tcontent_type: file.type === \"\" ? null : file.type,\n\t\t\t\t\t\tdata_base64: await toBase64(file),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t);\n\t\t},\n\t\tmeta: { failureTitle: \"Failed to upload files\" },\n\t});\n","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/gitbutlerapp/gitbutler/blob/58e5313667b857ef39a730e380af31816a7b1768/apps/lite/ui/src/api/mutations.ts#L286-L322","documentation":"Thrown by the useUploadFiles mutation when any file in the array exceeds UPLOAD_SIZE_LIMIT. The mutation validates all files up front via oversizedFile(files) and rejects with a human-readable message naming the offending file, its size in MB, and the limit. This prevents oversized payloads from being sent to the API.","triggerScenarios":"Calling the useUploadFiles mutation with an array containing at least one File whose size > UPLOAD_SIZE_LIMIT (the configured MB limit, compared in oversizedFile).","commonSituations":"User attaches a large image/video/log via chat/file-drop UI; paste of a large screenshot; batch upload where one file among many is oversized.","solutions":["Validate file sizes client-side before invoking the mutation and reject or warn on oversized files.","Compress or downscale large images before upload.","Catch the mutation error and show its message (it is already user-friendly) in the upload UI."],"exampleFix":"// before\nawait uploadFilesMutation.mutateAsync(files);\n// after\nconst tooLarge = files.find(f => f.size > UPLOAD_SIZE_LIMIT);\nif (tooLarge) {\n  toast.error(`${tooLarge.name} exceeds the upload limit`);\n  return;\n}\nawait uploadFilesMutation.mutateAsync(files);","handlingStrategy":"validation","validationCode":"const tooLarge = files.find(f => f.size > UPLOAD_SIZE_LIMIT);\nif (tooLarge) {\n  showToast(`${tooLarge.name} exceeds the ${UPLOAD_SIZE_LIMIT / 1024 / 1024} MB limit`);\n  return;\n}","typeGuard":null,"tryCatchPattern":"try {\n  await uploadFiles(files);\n} catch (e) {\n  showToast(e instanceof Error ? e.message : 'Upload failed');\n}","preventionTips":["Validate file sizes in the file picker/drop handler before accepting files","Compress or downscale large images before upload","Surface the limit in the upload UI up front"],"tags":["upload","file-size","validation"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"58e5313667b857ef39a730e380af31816a7b1768","analyzedAt":"2026-09-18T06:50:32.052Z","contentChangedAt":"2026-09-18T06:50:32.052Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}