gitroomhq/postiz-app · error · HttpException
Unsupported file type.
Error message
Unsupported file type.
What it means
After downloading, uploadsFromUrl sniffs the file's magic bytes with fileTypeFromBuffer and checks the detected MIME against a whitelist (PUBLIC_API_ALLOWED_MIME). If detection fails or the type isn't whitelisted, it throws 400 'Unsupported file type.' — the extension in the URL is irrelevant, only actual content is trusted.
Source
Thrown at apps/backend/src/public-api/routes/v1/public.integrations.controller.ts:139
}
if (!response.ok) {
throw new HttpException({ msg: 'Failed to fetch URL' }, 400);
}
// Guard against OOM: bail out before buffering the whole body into memory.
// Content-Length may be absent or wrong, so we re-check the real size after
// download too. The type isn't known yet (sniffed below), so the pre-check
// uses the largest allowed cap (video).
const maxDownloadSize = getMaxSize('video/mp4');
const declaredSize = Number(response.headers.get('content-length'));
if (declaredSize && declaredSize > maxDownloadSize) {
throw new HttpException({ msg: 'File is too large.' }, 400);
}
const buffer = Buffer.from(await response.arrayBuffer());
const detected = await fileTypeFromBuffer(buffer);
if (!detected || !PUBLIC_API_ALLOWED_MIME.has(detected.mime)) {
throw new HttpException({ msg: 'Unsupported file type.' }, 400);
}
if (buffer.length > getMaxSize(detected.mime)) {
throw new HttpException({ msg: 'File is too large.' }, 400);
}
const mimetype = detected.mime;
const ext = detected.ext;
const getFile = await this.storage.uploadFile({
buffer,
mimetype,
size: buffer.length,
path: '',
fieldname: '',
destination: '',
stream: new Readable(),
filename: '',View on GitHub (pinned to 0f1647f749)
Solutions
- Download the file locally and run `file` or a magic-byte checker to confirm its real type
- Convert/re-encode the asset to a whitelisted format (standard jpeg/png/mp4 etc.)
- If the URL returns an HTML error/login page, fix the link or make the asset directly fetchable (public, no auth wall)
- Check PUBLIC_API_ALLOWED_MIME in the codebase for the exact accepted list
Example fix
// before
{ "url": "https://example.com/photo.heic" }
// after
{ "url": "https://example.com/photo.jpg" } // re-encoded to a whitelisted format Defensive patterns
Strategy: type-guard
Validate before calling
const res = await fetch(url);
const buf = Buffer.from(await res.arrayBuffer());
const sig = buf.subarray(0, 12).toString('hex');
const known = { 'ffd8ff': 'jpeg', '89504e47': 'png', '66747966': 'mp4' /* etc */ };
if (!Object.keys(known).some(k => sig.startsWith(k))) throw new Error('Not a whitelisted media type'); Type guard
import { fileTypeFromBuffer } from 'file-type';
const isAllowedMediaType = async (buf: Buffer): Promise<boolean> => {
const t = await fileTypeFromBuffer(buf);
return !!t && ALLOWED_MIME.has(t.mime); // mirror PUBLIC_API_ALLOWED_MIME
}; Try / catch
try {
await api.uploadsFromUrl({ url });
} catch (e) {
if (e?.response?.data?.msg === 'Unsupported file type.') {
// re-encode the asset and retry; don't trust the file extension
}
} Prevention
- Serve real media bytes, not HTML error/login pages
- Re-encode HEIC/SVG/obscure formats to jpeg/png/mp4
- Remember: magic bytes decide, extensions are ignored
When it happens
Trigger: POST /public/v1/uploads/from-url with a URL serving an SVG, GIF variants, HEIC, text/html (an error page), or any binary whose magic bytes aren't in the whitelist. Also happens when the URL returns an HTML login/error page instead of the media, or when detection fails on truncated/empty bodies.
Common situations: Pointing at an HTML page behind auth rather than the asset; unusual formats like HEIC/AVIF/WebP variants not in the allowlist; renamed files (a .jpg that's actually a PDF); empty responses from misconfigured CDNs.
Related errors
- File is too large.
- All media must be uploaded through our upload API route and
- Unsupported file type.
- Unsupported file type.
- Failed to fetch URL
AI-assisted analysis of gitroomhq/postiz-app@0f1647f749 (2026-08-27).
Data as JSON: /api/errors/67509b4162d7c4a4.
Report an issue: GitHub.