{"record":{"id":"7bdef7b01928b719","repo":"mckaywrigley/chatbot-ui","slug":"error-uploading-file","errorCode":null,"errorMessage":"Error uploading file","messagePattern":"Error uploading file","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db/storage/files.ts","lineNumber":31,"sourceCode":"    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}\n\nexport const deleteFileFromStorage = async (filePath: string) => {\n  const { error } = await supabase.storage.from(\"files\").remove([filePath])\n\n  if (error) {\n    toast.error(\"Failed to remove file!\")\n    return\n  }\n}\n\nexport const getFileFromStorage = async (filePath: string) => {\n  const { data, error } = await supabase.storage\n    .from(\"files\")\n    .createSignedUrl(filePath, 60 * 60 * 24) // 24hrs","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/mckaywrigley/chatbot-ui/blob/81328b61d2a4ab597a7a057be70e785cf756d9f8/db/storage/files.ts#L13-L49","documentation":"Thrown by uploadFile when supabase.storage.from(\"files\").upload(...) with upsert: true returns an error. Supabase Storage reports bucket-not-found, RLS policy violations, duplicate-object conflicts, or payload-too-large through the returned error object, which this code flattens into a generic message. The upload path is base64(file_id) nested under user_id, so policy matching depends on that folder layout.","triggerScenarios":"Uploading a file when the 'files' bucket is absent; the authenticated user's JWT failing an INSERT/UPDATE policy on files/user_id/*; expired Supabase session (anon role can't insert); wrong project env vars; or a file exactly at the limit hitting the server's object size cap.","commonSituations":"Fresh environment missing the 'files' bucket; storage policies written for a different folder scheme than user_id/base64(file_id); token refresh not wired into the browser client; .env.local differing between dev and deployed builds.","solutions":["Log the returned error — error.message distinguishes 'Bucket not found' from 'row-level security' from 'Duplicate'.","Ensure the 'files' bucket exists and has INSERT plus UPDATE policies allowing auth.uid() = (storage.foldername(name))[1].","Confirm a valid authenticated session exists before upload (supabase.auth.getSession()) and refresh if expired.","Double-check NEXT_PUBLIC_SUPABASE_URL/ANON_KEY for the environment performing the upload."],"exampleFix":"// before\nif (error) {\n  throw new Error(\"Error uploading file\")\n}\n\n// after\nif (error) {\n  throw new Error(`Error uploading file: ${error.message}`)\n}","handlingStrategy":"try-catch","validationCode":"const { data: session } = await supabase.auth.getSession()\nif (!session.session) throw new Error(\"Authentication required to upload files\")","typeGuard":"const isFileUploadCandidate = (f: File): boolean =>\n  f.size > 0 && f.size <= Number(process.env.NEXT_PUBLIC_USER_FILE_SIZE_LIMIT || 1e7)","tryCatchPattern":"try {\n  const path = await uploadFile(file, payload)\n} catch (e) {\n  if (e instanceof Error && e.message === \"Error uploading file\") {\n    toast.error(\"Upload failed — check your connection and try again.\")\n  } else { throw e }\n}","preventionTips":["Provision the 'files' bucket plus INSERT/UPDATE policies as part of environment setup (migration script).","Ensure sessions are refreshed before long-running upload flows.","Surface the underlying Supabase error.message in logs to cut diagnosis time."],"tags":["supabase","storage","upload","rls","files"],"backgroundTag":"supabase-storage-upload-failed","analyzedSha":"81328b61d2a4ab597a7a057be70e785cf756d9f8","analyzedAt":"2026-08-27T19:24:42.689Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}