Short answer
Don’t use the user’s file name as the path. Build the path from the user ID and a random ID plus a cleaned extension, upload with that, and save the original name in your own table so you can show it later.
Rather not fix it yourself? App Fix Ticket starts with a fixed-price diagnosis, then a fixed price for the fix before any fix work.
Why the key is invalid, and the fix
01
The file name has accents, emoji or other scripts
“The specified key is invalid.” Supabase docs, Storage error codes (InvalidKey)
A name like résumé.pdf, a photo named with an emoji, or a file name in Arabic or Chinese fails, because Storage allows only plain Latin letters, digits and some punctuation.
02
The name has a character outside the allowed list
“File names can only include the following characters: Alphanumeric: A-Z, a-z, 0-9” Supabase docs, Storage limits (File name restrictions)
Characters such as #, %, [ ], { }, < >, ^, ~ and | aren’t on the list. Spaces, &, ?, + and = are allowed. A slash is read as a folder, so a name with a slash creates folders you didn’t mean to make.
03
The path comes straight from user input
Generate the path instead, and keep the display name in a column next to the path.
const ext = file.name.includes('.') ? file.name.split('.').pop().toLowerCase().replace(/[^a-z0-9]/g, '') : ''; const path = `${user.id}/${crypto.randomUUID()}${ext ? '.' + ext : ''}`; const { error } = await supabase.storage.from('uploads').upload(path, file); if (!error) await supabase.from('files').insert({ path, name: file.name });04
A move or copy uses the old name
move() and copy() take a new path too, so build that path the same way. Renaming a file to the user’s new title brings the same error back.
Checked against the vendor’s docs on : Supabase docs: Storage error codes; Supabase docs: Storage limits.
Rather hand it over?
Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.
- from $450App Fix TicketOne reproducible bug in an existing mobile or web app, diagnosed and fixed.See scope and start
- from $450AI-Built App RescueA Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.See scope and start
“Very responsive, attentive to fixing bugs, and completed the project as needed! Thank you!”
Related: Supabase Storage EntityTooLarge · Supabase Storage bucket not found · Supabase Storage bucket is public · Supabase Storage MIME type error · Supabase Storage resource already exists