Budibase/budibase · error · HTTPError

file is required

Error message

file is required

What it means

Thrown by uploadAgentFile when the multipart request contains no file under any of the accepted field names ('file', 'knowledgeBaseFile', 'upload'). The controller normalizes ctx.request.files and, finding nothing, rejects with HTTP 400 because knowledge ingestion requires an actual uploaded file.

Source

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

  ctx.status = 200
}

export async function uploadAgentFile(
  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)

View on GitHub (pinned to a81a902e9a)

Solutions

  1. Attach the file as multipart/form-data under the field name 'file' (or 'knowledgeBaseFile'/'upload').
  2. Verify the request Content-Type is multipart/form-data and the form has enctype='multipart/form-data'.
  3. Confirm the server's multipart body-parsing middleware is configured so ctx.request.files is populated.
  4. Check that no reverse proxy (e.g. nginx client_max_body_size) is dropping the file part.

Example fix

// before
await fetch(`/api/ai/agents/${agentId}/operations/${opId}/files`, { method: "POST", body: JSON.stringify({ data }) })
// after
const form = new FormData()
form.append("file", new Blob([buffer]), "doc.pdf")
await fetch(`/api/ai/agents/${agentId}/operations/${opId}/files`, { method: "POST", body: form })
Defensive patterns

Strategy: validation

Validate before calling

function hasUpload(files) {
  return Boolean(files && (files.file || files.knowledgeBaseFile || files.upload))
}
if (!hasUpload(ctx.request.files)) throw new Error("file is required")

Type guard

function isUploadedFile(f) {
  return Boolean(f && typeof f === "object" && typeof (f.filepath ?? f.path) === "string")
}

Try / catch

try {
  const res = await api.uploadAgentFile(agentId, operationId, form)
} catch (err) {
  if (err.status === 400 && err.message === "file is required") {
    // prompt user to attach a file
  } else throw err
}

Prevention

When it happens

Trigger: POSTing to the agent file upload endpoint without multipart/form-data; attaching the file under a field name other than file/knowledgeBaseFile/upload; sending a JSON body instead of multipart; body-parser middleware not enabled so ctx.request.files is undefined.

Common situations: Hand-rolled curl or fetch calls using the wrong form field name; Postman/Swagger requests left on raw JSON body type; frontend form missing enctype='multipart/form-data'; a proxy stripping the file part.

Understand the failure class

Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.

Related errors


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