{"record":{"id":"21831e1d66a5bcbc","repo":"Budibase/budibase","slug":"openapi-template-must-be-a-yaml-or-json-file","errorCode":null,"errorMessage":"OpenAPI template must be a YAML or JSON file","messagePattern":"OpenAPI template must be a YAML or JSON file","errorType":"http","errorClass":"HTTPError","httpStatus":400,"severity":"error","filePath":"packages/server/src/api/controllers/restTemplate.ts","lineNumber":43,"sourceCode":"    return undefined\n  }\n  return {\n    filepath: upload.filepath,\n    filename: upload.originalFilename,\n  }\n}\n\nconst getFileExtension = (\n  filename: string\n): CustomRestTemplateFileExtension => {\n  const extension = filename.split(\".\").pop()?.toLowerCase()\n  if (extension === \"json\") {\n    return \"json\"\n  }\n  if (extension === \"yaml\" || extension === \"yml\") {\n    return \"yaml\"\n  }\n  throw new HTTPError(\"OpenAPI template must be a YAML or JSON file\", 400)\n}\n\nexport const fetch = async (\n  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  }","sourceCodeStart":25,"sourceCodeEnd":61,"githubUrl":"https://github.com/Budibase/budibase/blob/a81a902e9a8fe55b467d106765f6638f12e35c49/packages/server/src/api/controllers/restTemplate.ts#L25-L61","documentation":"`getFileExtension` (used by `fileExtension` during custom REST template upload) accepts only `json`, `yaml`, or `yml` extensions. Anything else throws this 400 HTTPError, because custom REST templates must be OpenAPI documents in JSON or YAML format.","triggerScenarios":"Uploading a file whose extension is anything other than .json/.yaml/.yml — e.g. .txt, .xml, .wsdl, .md, or a file with no extension.","commonSituations":"Users upload a Postman collection (JSON content but named .txt) or a WSDL/XML spec; file downloaded without an extension; macOS renaming files stripping extensions; trying to import RAML or Swagger UI HTML exports.","solutions":["Rename the file to have a .json, .yaml, or .yml extension that matches its content","Convert non-OpenAPI formats (WSDL, RAML, Swagger 2.0) to OpenAPI 3 JSON/YAML before upload","Re-export the spec from the source tool choosing the OpenAPI 3 YAML/JSON option"],"exampleFix":"// before\nupload({ file: mySpec.xml })\n// after\nupload({ file: convertToOpenApi3Yaml(mySpec) }) // mySpec.yaml","handlingStrategy":"validation","validationCode":"const ext = file.name.split(\".\").pop().toLowerCase()\nif (![\"json\", \"yaml\", \"yml\"].includes(ext)) {\n  throw new Error(`Unsupported template extension: .${ext}`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  await uploadRestTemplate({ file })\n} catch (e) {\n  if (e.status === 400 && String(e.message).includes(\"must be a YAML or JSON file\")) {\n    // prompt user to pick a .json/.yaml file\n  }\n}","preventionTips":["Validate file extension client-side before upload","Restrict file input accept attribute to `.json,.yaml,.yml`","Convert legacy formats (WSDL/RAML/Swagger 2) to OpenAPI 3 first","Ensure exported files keep their extension when downloaded"],"tags":["rest-template","validation","file-upload"],"backgroundTag":"invalid-file-format","analyzedSha":"a81a902e9a8fe55b467d106765f6638f12e35c49","analyzedAt":"2026-08-29T01:03:10.972Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}