{"record":{"id":"0edb6c781d89d9f7","repo":"mckaywrigley/chatbot-ui","slug":"error-deleting-old-image","errorCode":null,"errorMessage":"Error deleting old image","messagePattern":"Error deleting old image","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"db/storage/assistant-images.ts","lineNumber":25,"sourceCode":") => {\n  const bucket = \"assistant_images\"\n\n  const imageSizeLimit = 6000000 // 6MB\n\n  if (image.size > imageSizeLimit) {\n    throw new Error(`Image must be less than ${imageSizeLimit / 1000000}MB`)\n  }\n\n  const currentPath = assistant.image_path\n  let filePath = `${assistant.user_id}/${assistant.id}/${Date.now()}`\n\n  if (currentPath.length > 0) {\n    const { error: deleteError } = await supabase.storage\n      .from(bucket)\n      .remove([currentPath])\n\n    if (deleteError) {\n      throw new Error(\"Error deleting old image\")\n    }\n  }\n\n  const { error } = await supabase.storage\n    .from(bucket)\n    .upload(filePath, image, {\n      upsert: true\n    })\n\n  if (error) {\n    throw new Error(\"Error uploading image\")\n  }\n\n  return filePath\n}\n\nexport const getAssistantImageFromStorage = async (filePath: string) => {\n  try {","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/mckaywrigley/chatbot-ui/blob/81328b61d2a4ab597a7a057be70e785cf756d9f8/db/storage/assistant-images.ts#L7-L43","documentation":"Thrown by uploadAssistantImage when supabase.storage.from(\"assistant_images\").remove([currentPath]) returns an error while trying to delete the assistant's previous image before uploading a new one. The underlying StorageError is discarded and replaced with this generic message. It almost always means the stored assistant.image_path no longer exists in the bucket, or the current user lacks DELETE permission on that object.","triggerScenarios":"Calling uploadAssistantImage with an assistant whose image_path is set: the remove() call fails when (a) the object at image_path was already deleted or never committed, (b) the bucket 'assistant_images' is missing or misnamed, (c) the user's JWT doesn't satisfy a storage.objects DELETE policy for that path, or (d) the path was written by a different user_id prefix.","commonSituations":"Stale image_path in the assistants row after a manual bucket wipe or project migration; RLS storage policies that allow insert/update but not delete; switching between service-role and anon-key clients so the object owner differs; local dev pointing at a different Supabase project where the old object doesn't exist.","solutions":["Inspect the real cause by logging deleteError (and deleteError.message) before throwing — 'Object not found' vs 'row-level security' point to different fixes.","If the error is 'not found', treat deletion of a non-existent old image as non-fatal: proceed with the upload instead of throwing.","Add/adjust a storage.objects DELETE policy on assistant_images for the bucket owner (auth.uid() = (storage.foldername(name))[1]).","Verify the bucket 'assistant_images' exists in the target Supabase project and the client uses the correct project URL/keys."],"exampleFix":"// before\nif (deleteError) {\n  throw new Error(\"Error deleting old image\")\n}\n\n// after\nif (deleteError && !deleteError.message.includes(\"not found\")) {\n  console.error(\"Failed to delete old image:\", deleteError)\n  throw new Error(`Error deleting old image: ${deleteError.message}`)\n}","handlingStrategy":"try-catch","validationCode":"// Before uploading, optionally confirm the old object exists\nconst { data: list } = await supabase.storage\n  .from(\"assistant_images\")\n  .list(dirname(currentPath), { search: basename(currentPath) })\nif (!list?.some(o => o.name === basename(currentPath))) {\n  // old image already gone; skip delete\n}","typeGuard":"const hasOldImage = (a: { image_path: string | null }): boolean =>\n  typeof a.image_path === \"string\" && a.image_path.length > 0","tryCatchPattern":"try {\n  await uploadAssistantImage(assistant, image)\n} catch (e) {\n  if (e instanceof Error && e.message === \"Error deleting old image\") {\n    // old image missing/locked: retry upload skipping delete, or surface a toast\n    toast.error(\"Could not replace the old image. Please retry.\")\n  } else {\n    throw e\n  }\n}","preventionTips":["Treat 'old object not found' as non-fatal: log and continue with the upload instead of throwing.","Keep assistant.image_path in sync with actual bucket contents (clear it when the object is deleted elsewhere).","Maintain storage DELETE policies scoped to the object owner from day one."],"tags":["supabase","storage","delete","rls","assistant-images"],"backgroundTag":"supabase-storage-delete-failed","analyzedSha":"81328b61d2a4ab597a7a057be70e785cf756d9f8","analyzedAt":"2026-08-27T19:24:42.689Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}