Budibase/budibase · error · BadRequestError
File "${fileName}" has an invalid extension: "${extension}"
Error message
File "${fileName}" has an invalid extension: "${extension}" What it means
Thrown by uploadFile when the extension (lowercased) is in the InvalidFileExtensions blocklist from @budibase/shared-core. The check is enforced for public (unauthenticated) users and on non-self-hosted (cloud) deployments; self-hosted authenticated admins bypass it.
Source
Thrown at packages/server/src/api/controllers/static/index.ts:288
}
const extension = [...fileName.split(".")].pop()
if (!extension) {
throw new BadRequestError(
`File "${fileName}" has no extension, an extension is required to upload a file`
)
}
const extensionLower = extension.toLowerCase()
const isPublicUser =
ctx.roleId === roles.BUILTIN_ROLE_IDS.PUBLIC ||
ctx.user?.roleId === roles.BUILTIN_ROLE_IDS.PUBLIC
const enforceInvalidExtension = isPublicUser || !env.SELF_HOSTED
if (
enforceInvalidExtension &&
InvalidFileExtensions.includes(extensionLower)
) {
throw new BadRequestError(
`File "${fileName}" has an invalid extension: "${extension}"`
)
}
if (ACTIVE_CONTENT_EXTENSIONS.has(extensionLower)) {
throw new ActiveContentFileError(fileName)
}
const mimeType =
typeof rawMimeType === "string" ? rawMimeType.toLowerCase() : undefined
if (
mimeType &&
ACTIVE_CONTENT_MIME_TYPES.some(type => mimeType.includes(type))
) {
throw new ActiveContentFileError(fileName)
}
if (View on GitHub (pinned to a81a902e9a)
Solutions
- Rename or repackage the file with an allowed extension (e.g. zip it first)
- Host the file externally and link to it instead of uploading
- For self-hosted environments where this is intended, ensure env.SELF_HOSTED=true and upload as an authenticated non-public user
Example fix
// before upload 'installer.exe' as anonymous user in cloud // after zip to 'installer.zip' or host externally and link
Defensive patterns
Strategy: validation
Validate before calling
const BLOCKED = ['exe','bat','sh','cmd','com','scr','ps1'] // subset of InvalidFileExtensions
function isExtensionAllowed(name) {
const ext = (name.split('.').pop() || '').toLowerCase()
return !BLOCKED.includes(ext)
} Type guard
const isSafeExtension = (name: string): boolean =>
!InvalidFileExtensions.includes((name.split('.').pop() || '').toLowerCase()) Try / catch
try {
await api.uploadFile(fd)
} catch (err) {
if (err instanceof BadRequestError && err.message.includes('invalid extension')) {
// package the file (e.g. zip) or host externally
} else throw err
} Prevention
- Check extensions against the blocklist before uploading, especially as an anonymous user in cloud
- Zip binaries/scripts when distribution via attachments is required
- Remember self-hosted authenticated uploads are not subject to this filter
When it happens
Trigger: Uploading a file with a blacklisted extension (e.g. .exe, .bat, .sh) when the requester's roleId is PUBLIC or env.SELF_HOSTED is false.
Common situations: Distributing installers/scripts via Budibase attachments in cloud apps, or self-hosters confused because the same file works locally but is blocked in cloud.
Related errors
- File "${fileName}" has no extension, an extension is require
- File "${fileName}" contains active content which is not perm
- Invalid object store key: path traversal is not allowed.
- Stream to upload is invalid/undefined
- Only HTTP(S) URLs are allowed.
AI-assisted analysis of Budibase/budibase@a81a902e9a (2026-08-29).
Data as JSON: /api/errors/06288364fc3fbc7e.
Report an issue: GitHub.