{"record":{"id":"4453f99d514dad4d","repo":"windmill-labs/windmill","slug":"missing-file-relative-path","errorCode":null,"errorMessage":"Missing file relative path","messagePattern":"Missing file relative path","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/common/fileUpload/FileUpload.svelte","lineNumber":188,"sourceCode":"\tfunction getRandomFolderPrefix(): string {\n\t\tconst now = Date.now()\n\t\tconst randomNum = Math.floor(Math.random() * 65536)\n\t\treturn `windmill_uploads/upload_${now}_${randomNum}/`\n\t}\n\n\tlet uniqueFolderPrefix = getRandomFolderPrefix()\n\tlet uploadedFolderRoot: string | undefined = undefined\n\n\tasync function uploadFileToS3(fileToUpload: File & { path?: string }, fileToUploadKey: string) {\n\t\tif (fileToUpload === undefined || fileToUploadKey === undefined) {\n\t\t\treturn\n\t\t}\n\t\tlet path: string | undefined = undefined\n\t\tlet fileExtension: string | undefined = undefined\n\t\tif (folderOnly) {\n\t\t\tconst relativePath = fileToUpload.webkitRelativePath || fileToUpload.path\n\t\t\tif (!relativePath) {\n\t\t\t\tthrow new Error('Missing file relative path')\n\t\t\t}\n\t\t\tconst rootFolder = relativePath.split('/')[0]\n\t\t\tif (!rootFolder) {\n\t\t\t\tthrow new Error('Missing root folder')\n\t\t\t}\n\t\t\tif (uploadedFolderRoot && rootFolder !== uploadedFolderRoot) {\n\t\t\t\tthrow new Error('Uploading a file in a different root folder than the previous files')\n\t\t\t} else {\n\t\t\t\tuploadedFolderRoot = rootFolder\n\t\t\t}\n\t\t\tpath = uniqueFolderPrefix + relativePath\n\t\t} else if (randomFileKey) {\n\t\t\tfileExtension = fileToUpload.name.split('.').pop()\n\t\t\tif (emptyString(fileExtension)) {\n\t\t\t\tfileExtension = undefined\n\t\t\t}\n\t\t} else {\n\t\t\tpath =","sourceCodeStart":170,"sourceCodeEnd":206,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/common/fileUpload/FileUpload.svelte#L170-L206","documentation":"FileUpload.svelte's uploadFileToS3() computes each file's path for folder uploads from file.webkitRelativePath || file.path. When folderOnly is set and neither property exists, it throws 'Missing file relative path'.","triggerScenarios":"Uploading with folder-only mode using files that were not selected via a directory picker (drag-and-drop or programmatic File objects without webkitRelativePath/path).","commonSituations":"Files added via drag-and-drop (webkitdirectory metadata absent); constructing File objects in tests or code and passing them to the uploader; browser privacy/compat removing the path property.","solutions":["Select the folder via the directory input (webkitdirectory) so webkitRelativePath is populated","For drag-and-drop, use DataTransferItem.webkitGetAsEntry() to reconstruct relative paths before uploading","If uploading individual files, disable folderOnly mode"],"exampleFix":"// before\nconst file = new File([blob], 'a.txt') // no webkitRelativePath\n// after\n// let user pick via <input type=\"file\" webkitdirectory> so file.webkitRelativePath = 'root/a.txt'","handlingStrategy":"validation","validationCode":"const rel = (file as any).webkitRelativePath || (file as any).path\nif (folderOnly && !rel) {\n  console.error('Folder upload requires webkitRelativePath; use a webkitdirectory input')\n}","typeGuard":"function hasRelativePath(f: File): f is File & {webkitRelativePath: string} {\n  return f.webkitRelativePath !== ''\n}","tryCatchPattern":"try {\n  await uploadFileToS3(file)\n} catch (e) {\n  if (e.message === 'Missing file relative path') {\n    console.error('Use the directory picker for folder uploads', e)\n  } else throw e\n}","preventionTips":["Always upload folders via an <input type='file' webkitdirectory> selection","Reconstruct relative paths from webkitGetAsEntry() when supporting drag-and-drop","Disable folderOnly for plain file lists"],"tags":["file-upload","s3","browser-api"],"backgroundTag":"missing-webkitrelativepath","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}