{"record":{"id":"2019a18eef43c56b","repo":"Budibase/budibase","slug":"invalid-openapi-template-upload","errorCode":null,"errorMessage":"Invalid OpenAPI template upload","messagePattern":"Invalid OpenAPI template upload","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/api/controllers/restTemplate.ts","lineNumber":65,"sourceCode":"  ctx: UserCtx<void, FetchCustomRestTemplatesResponse>\n) => {\n  ctx.body = await sdk.restTemplates.fetch()\n}\n\nexport const upload = async (\n  ctx: UserCtx<\n    UploadCustomRestTemplateRequest,\n    UploadCustomRestTemplateResponse\n  >\n) => {\n  const file = ctx.request.files?.file\n  if (!file || Array.isArray(file)) {\n    throw new HTTPError(\"Exactly one OpenAPI template file is required\", 400)\n  }\n\n  const uploadDetails = getUploadDetails(file)\n  if (!uploadDetails) {\n    throw new HTTPError(\"Invalid OpenAPI template upload\", 400)\n  }\n\n  try {\n    const name = ctx.request.body.name\n    const description = ctx.request.body.description\n    if (typeof name !== \"string\" || !name.trim()) {\n      throw new HTTPError(\"Template name is required\", 400)\n    }\n    if (typeof description !== \"string\") {\n      throw new HTTPError(\"Template description is required\", 400)\n    }\n\n    const fileExtension = getFileExtension(uploadDetails.filename)\n    const data = await readFile(uploadDetails.filepath, \"utf8\")\n    let importer\n    let info\n    try {\n      importer = await createImporter({ data })","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/restTemplate.ts#L47-L83","documentation":"After file count validation, `upload` calls `getUploadDetails(file)` which derives upload metadata (path/name) from the uploaded file. If it returns falsy — e.g. the file object lacks the expected `name`/`originalFilename`/path properties or is otherwise malformed — the controller throws this 400 HTTPError. It usually indicates the file object doesn't look like a normal multipart upload.","triggerScenarios":"Uploading with a client that omits the filename metadata (some HTTP libraries send a bare body), streaming endpoints that construct file objects without names, or middleware transformations that strip standard fields from the file object.","commonSituations":"Custom HTTP clients that send multipart without filename; proxies/gateways rewriting multipart parts and dropping metadata; tests posting raw buffers instead of proper multipart; unusual characters or empty filenames.","solutions":["Send a proper multipart/form-data request including a filename (e.g. `curl -F file=@spec.yaml`)","Verify the file object has standard fields (`originalFilename`/`name`, `filepath`) on the server","Check that proxies/middleware aren't stripping multipart metadata","Update tests to upload via multipart instead of raw buffers"],"exampleFix":"// before\nawait fetch(url, { method: \"POST\", body: fileBuffer }) // no multipart metadata\n// after\nconst form = new FormData()\nform.append(\"file\", new Blob([fileBuffer]), \"spec.yaml\")\nawait fetch(url, { method: \"POST\", body: form })","handlingStrategy":"validation","validationCode":"const f = formData.get(\"file\")\nif (!(f instanceof File) || !f.name || !f.name.trim()) {\n  throw new Error(\"Uploaded file must include a filename\")\n}","typeGuard":null,"tryCatchPattern":"try {\n  await uploadRestTemplate(form)\n} catch (e) {\n  if (e.status === 400 && String(e.message).includes(\"Invalid OpenAPI template upload\")) {\n    // ensure the multipart part carries a filename and retry\n  }\n}","preventionTips":["Always send multipart uploads with an explicit filename","Don't post raw buffers to upload endpoints","Test upload flows through any reverse proxies in the path","Include name/description string fields in the upload body as required"],"tags":["file-upload","rest-template","multipart"],"backgroundTag":"invalid-file-format","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}