gitroomhq/postiz-app · error · BadRequestException
Unsupported file type.
Error message
Unsupported file type.
What it means
The upload validation pipe sniffs the real content type from the bytes via fileTypeFromBuffer and rejects anything whose detected MIME is not in ALLOWED_MIME_TYPES. Client-declared mimetype and file extension are ignored, so renaming a file or spoofing the Content-Type header will not bypass it.
Source
Thrown at libraries/nestjs-libraries/src/upload/custom.upload.validation.ts:38
@Injectable()
export class CustomFileValidationPipe implements PipeTransform {
async transform(value: any) {
if (!value || typeof value !== 'object') {
return value;
}
// Skip non-file parameters (org, body, query, etc.)
if (!('buffer' in value) && !('mimetype' in value) && !('fieldname' in value)) {
return value;
}
if (!value.buffer || !Buffer.isBuffer(value.buffer)) {
throw new BadRequestException('Invalid file upload.');
}
const detected = await fileTypeFromBuffer(value.buffer);
if (!detected || !ALLOWED_MIME_TYPES.has(detected.mime)) {
throw new BadRequestException('Unsupported file type.');
}
const maxSize = getMaxSize(detected.mime);
if (value.size > maxSize) {
throw new BadRequestException(
`File size exceeds the maximum allowed size of ${maxSize} bytes.`
);
}
value.mimetype = detected.mime;
const safeBase = (value.originalname || 'upload')
.replace(/\.[^./\\]*$/, '')
.replace(/[\\/]/g, '_')
.slice(0, 100) || 'upload';
value.originalname = `${safeBase}.${detected.ext}`;
return value;
}View on GitHub (pinned to 0f1647f749)
Solutions
- Verify the real content with `file` command or a hex dump of the first bytes
- Convert the file to an allowed format (png/jpeg/webp/gif or allowed video) before upload
- If the format should be supported, add it to ALLOWED_MIME_TYPES in custom.upload.validation.ts and redeploy
- For SVG, consider sanitizing then serving with a safe Content-Type rather than allowing raw upload
Example fix
// before
form.append('file', new File([svgText], 'logo.svg', { type: 'image/svg+xml' })); // rejected
// after: rasterize to png first
const png = await rasterizeSvg(svgText);
form.append('file', new File([png], 'logo.png', { type: 'image/png' })); Defensive patterns
Strategy: validation
Validate before calling
import { fileTypeFromBuffer } from 'file-type';
async function assertAllowed(buffer: Buffer, allow: Set<string>) {
const t = await fileTypeFromBuffer(buffer);
if (!t || !allow.has(t.mime)) throw new Error(`Rejecting ${t?.mime ?? 'unknown'} file`);
} Type guard
const isSupportedUpload = async (b: Buffer) => { const t = await fileTypeFromBuffer(b); return !!t && ALLOWED_MIME_TYPES.has(t.mime); }; Try / catch
try { await api.upload(form); } catch (e) { if (/Unsupported file type/.test(String(e))) notify('Convert to PNG/JPEG/GIF/WebP or MP4 and retry'); else throw e; } Prevention
- Convert exotic formats (SVG, HEIC) before upload
- Never trust extension or client Content-Type
- Maintain one shared allow-list across upload paths
When it happens
Trigger: Uploading a file whose magic bytes don't match a known signature (text files, SVGs, HEIC, docs, executables), an empty/truncated buffer, or a supported extension whose actual content is different (e.g. an .exe renamed to .png).
Common situations: SVG logo uploads (SVG has no magic-byte signature file-type recognizes in many versions); HEIC photos from iPhones; uploading PDFs or zip archives where only images/video are allowed; corrupted files from a failed download.
Related errors
- Unsupported file type.
- Unsupported file type.
- File is too large.
- All media must be uploaded through our upload API route and
- Invalid file upload.
AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27).
Data as JSON: /api/errors/c6540fa8e75c4b3f.
Report an issue: GitHub.