Budibase/budibase · error · HTTPError

Invalid upload payload

Error message

Invalid upload payload

What it means

Thrown when a file entry exists in ctx.request.files but the normalized upload object exposes neither filepath nor path, so the controller cannot locate the temp file on disk. Indicates a malformed or non-standard upload payload shape rather than a missing file.

Source

Thrown at packages/server/src/api/controllers/ai/files.ts:194

  ctx: UserCtx<
    void,
    AgentFileUploadResponse,
    { agentId: string; operationId: string }
  >
) {
  const { agentId, operationId } = ctx.params
  const upload = normalizeUpload(
    ctx.request.files?.file ||
      ctx.request.files?.knowledgeBaseFile ||
      ctx.request.files?.upload
  )

  if (!upload) {
    throw new HTTPError("file is required", 400)
  }
  const filePath = upload.filepath || upload.path
  if (!filePath) {
    throw new HTTPError("Invalid upload payload", 400)
  }

  const filename = upload.originalFilename || upload.name || "agent-document"
  const mimetype = upload.mimetype || upload.type
  const fileSize =
    typeof upload.size === "number"
      ? upload.size
      : Number(upload.size) || undefined
  if (!isKnowledgeFileSupported({ filename, mimetype })) {
    await unlinkSafe(filePath)
    throw new HTTPError("Unsupported file type for knowledge ingestion", 400)
  }

  const buffer = await readFile(filePath)

  try {
    const updated = await sdk.ai.rag.uploadFileForOperation(
      agentId,

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Use the standard multipart parser configuration so uploads expose filepath (tmp-file storage, e.g. formidable defaults).
  2. Inspect the parsed upload object shape and confirm it has filepath or path before the handler runs.
  3. Check middleware ordering so multipart parsing executes before the route handler.
  4. Send a genuine file part (not a text field) named file/knowledgeBaseFile/upload.

Example fix

// before
app.use(koaBody({ multipart: true }))
// after
app.use(koaBody({ multipart: true, formidable: { uploadDir: os.tmpdir(), keepExtensions: true } }))
Defensive patterns

Strategy: type-guard

Validate before calling

const upload = files?.file || files?.knowledgeBaseFile || files?.upload
const filePath = upload?.filepath || upload?.path
if (!filePath) throw new Error("Invalid upload payload")

Type guard

function hasReadablePath(u) {
  return Boolean(u && typeof u === "object" && (typeof u.filepath === "string" || typeof u.path === "string"))
}

Try / catch

try {
  await uploadAgentFile(ctx)
} catch (err) {
  if (err.message === "Invalid upload payload") {
    // inspect parser config / upload object shape
  } else throw err
}

Prevention

When it happens

Trigger: The multipart parser produced an upload object lacking both filepath and path (e.g. a memoryStorage parser returning a Buffer without a path); custom middleware reshaping ctx.request.files; a client sending form values coerced into 'file' fields instead of real file parts.

Common situations: Switching koa-body/busboy options (multipart, memoryStorage) without accounting for the different upload shape; custom normalization middleware dropping fields; using a non-standard parsing library that stores content under different keys.

Related errors


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