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

  1. Upload with a proper multipart form including a file field (curl -F "file=@plugin.tar.gz")
  2. Ensure Content-Type is multipart/form-data and the field name matches the server's expectation
  3. Check proxy (nginx client_max_body_size) isn't truncating large tarballs
  4. 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

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


AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29). Data as JSON: /api/errors/9c611314a16e1a42. Report an issue: GitHub.