Budibase/budibase · error · Error
File is not valid - cannot upload.
Error message
File is not valid - cannot upload.
What it means
fileUpload validates the uploaded plugin file before extracting: a missing originalFilename or filepath (the multipart fields populated by the upload middleware) means the file never made it through intact, so this Error is thrown. It is a guard against empty or malformed uploads.
Source
Thrown at packages/server/src/api/controllers/plugin/file.ts:14
import {
createTempFolder,
deleteFolderFileSystem,
getPluginMetadata,
extractTarball,
} from "../../../utilities/fileSystem"
import { KoaFile } from "@budibase/types"
export async function fileUpload(file: KoaFile) {
const filename = file.originalFilename
const filePath = file.filepath
if (!filename || !filePath) {
throw new Error("File is not valid - cannot upload.")
}
if (!filename.endsWith(".tar.gz")) {
throw new Error("Plugin must be compressed into a gzipped tarball.")
}
const path = createTempFolder(filename.split(".tar.gz")[0])
try {
await extractTarball(filePath, path)
return await getPluginMetadata(path)
} catch (err) {
deleteFolderFileSystem(path)
throw err
}
}
View on GitHub (pinned to a81a902e9a)
Solutions
- Upload with a proper multipart form including a file field (curl -F "file=@plugin.tar.gz")
- Ensure Content-Type is multipart/form-data and the field name matches the server's expectation
- Check proxy (nginx client_max_body_size) isn't truncating large tarballs
- Retry the upload; verify the file exists and is non-empty before sending
Example fix
// before
curl -X POST https://example.com/api/plugins -H "Content-Type: application/json" -d '{}'
// after
curl -X POST https://example.com/api/plugins -F "file=@./plugin.tar.gz" Defensive patterns
Strategy: validation
Validate before calling
const form = new FormData()
const file = fs.readFileSync("./plugin.tar.gz")
if (!file.length) throw new Error("file is empty")
form.append("file", new Blob([file]), "plugin.tar.gz")
await api.post("/api/plugins", form)
Type guard
const isUploadable = (f: File | null): f is File => f !== null && f.size > 0 && f.name.length > 0
Try / catch
try {
await api.post("/api/plugins", form)
} catch (err) {
if (err.message === "File is not valid - cannot upload.") {
console.error("Upload rejected: check multipart field name and file presence")
} else { throw err }
}
Prevention
- Always send multipart/form-data with the correct file field name
- Verify the file exists and is non-empty before uploading
- Check proxy body-size limits for large tarballs
- Don't set Content-Type manually when using FormData
When it happens
Trigger: POSTing to the plugin upload endpoint without a valid multipart file field; a 0-byte or stream-truncated upload where koa-body/formidable doesn't populate originalFilename/filepath; uploading with the wrong form field name.
Common situations: curl calls missing -F file=@...; proxy/nginx stripping or buffering the multipart body; Content-Type not multipart/form-data; client aborting mid-upload; oversized uploads rejected upstream leaving empty temp files.
Related errors
- Plugin must be compressed into a gzipped tarball.
- No file provided
- Attempted to upload a file without a filename
- Attempted to upload a file without a path
- Stream to upload is invalid/undefined
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/9c611314a16e1a42.
Report an issue: GitHub.