{"record":{"id":"832c0d6884003d77","repo":"mckaywrigley/chatbot-ui","slug":"file-must-be-less-than-math-floor-size-limit-1","errorCode":null,"errorMessage":"File must be less than ${Math.floor(SIZE_LIMIT / 1000000)}MB","messagePattern":"File must be less than (.+?)MB","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"db/storage/files.ts","lineNumber":17,"sourceCode":"import { supabase } from \"@/lib/supabase/browser-client\"\nimport { toast } from \"sonner\"\n\nexport const uploadFile = async (\n  file: File,\n  payload: {\n    name: string\n    user_id: string\n    file_id: string\n  }\n) => {\n  const SIZE_LIMIT = parseInt(\n    process.env.NEXT_PUBLIC_USER_FILE_SIZE_LIMIT || \"10000000\"\n  )\n\n  if (file.size > SIZE_LIMIT) {\n    throw new Error(\n      `File must be less than ${Math.floor(SIZE_LIMIT / 1000000)}MB`\n    )\n  }\n\n  const filePath = `${payload.user_id}/${Buffer.from(payload.file_id).toString(\"base64\")}`\n\n  const { error } = await supabase.storage\n    .from(\"files\")\n    .upload(filePath, file, {\n      upsert: true\n    })\n\n  if (error) {\n    throw new Error(\"Error uploading file\")\n  }\n\n  return filePath\n}","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/mckaywrigley/chatbot-ui/blob/81328b61d2a4ab597a7a057be70e785cf756d9f8/db/storage/files.ts#L1-L35","documentation":"Thrown by uploadFile when the File's byte size exceeds NEXT_PUBLIC_USER_FILE_SIZE_LIMIT (parsed as an integer, defaulting to 10000000 bytes = 10MB). This is a purely client-side guard executed before any network call to Supabase Storage. The template interpolates Math.floor(SIZE_LIMIT / 1000000) so the message shows the limit in whole MB.","triggerScenarios":"Passing a file with file.size > SIZE_LIMIT — e.g. an 11MB PDF against the 10MB default; or setting NEXT_PUBLIC_USER_FILE_SIZE_LIMIT to a small value like '1000000' so previously fine files now throw. Because parseInt stops at the first non-digit, a malformed value like '10mb' parses as 10 (bytes), rejecting nearly everything.","commonSituations":"Env var set as '10MB' or '10 mb' instead of raw bytes; changing the limit per environment but only rebuilding one; large exports/recordings users try to attach; forgetting that NEXT_PUBLIC_ vars are inlined at build time so runtime .env changes have no effect until rebuild.","solutions":["Compress or split the file, or raise NEXT_PUBLIC_USER_FILE_SIZE_LIMIT to an explicit byte value (e.g. '50000000') and rebuild the app.","Verify the env var is a plain byte count with no unit suffix — '10mb' parseInts to 10 and breaks the check.","Warn users in the UI before upload by checking file.size against the same limit client-side.","Keep the Supabase Storage bucket's own size cap in sync if you raise this limit."],"exampleFix":"// before\nconst SIZE_LIMIT = parseInt(\n  process.env.NEXT_PUBLIC_USER_FILE_SIZE_LIMIT || \"10000000\"\n)\n\n// after\nconst SIZE_LIMIT = Number(\n  process.env.NEXT_PUBLIC_USER_FILE_SIZE_LIMIT || \"10000000\"\n)\nif (!Number.isFinite(SIZE_LIMIT) || SIZE_LIMIT <= 0) {\n  throw new Error(\"Invalid NEXT_PUBLIC_USER_FILE_SIZE_LIMIT\")\n}","handlingStrategy":"validation","validationCode":"const SIZE_LIMIT = Number(process.env.NEXT_PUBLIC_USER_FILE_SIZE_LIMIT || \"10000000\")\nif (file.size > SIZE_LIMIT) {\n  toast.error(`File too large — max ${Math.floor(SIZE_LIMIT / 1_000_000)}MB`)\n  // stop before calling uploadFile\n}","typeGuard":"const isWithinLimit = (f: File, limit: number): boolean =>\n  f.size <= limit && Number.isFinite(limit)","tryCatchPattern":"try {\n  await uploadFile(file, payload)\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith(\"File must be less than\")) {\n    toast.error(e.message) // user-fixable; no retry needed\n  } else {\n    throw e\n  }\n}","preventionTips":["Validate file.size in the picker UI before submission.","Keep NEXT_PUBLIC_USER_FILE_SIZE_LIMIT as raw bytes (no 'MB' suffix) and validate it parses to a sane positive number.","Remember NEXT_PUBLIC_ vars are inlined at build time — rebuild after changing them."],"tags":["file-size","validation","env-var","nextjs","files"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"81328b61d2a4ab597a7a057be70e785cf756d9f8","analyzedAt":"2026-08-27T19:24:42.689Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}