Support Ticket Attachment Preview Fallbacks
Handle broken and unpreviewable attachments in support ticket systems with typed attachment preview placeholder images that communicate file type without a broken icon.
Support ticket systems display attachment thumbnails inline in the conversation thread. When an attachment is a non-image file or a broken image URL, the default broken image icon is unhelpful—it gives the support agent no information about what the customer attached. Attachment preview placeholder images replace the broken icon with a type-aware visual that communicates file format at a glance.
The fallback.pics API generates file-type labeled placeholder images from a URL. Map each MIME type or file extension to a colored placeholder and your support UI handles every attachment type consistently.
The broken attachment problem
Why support ticket attachment previews break
Support ticket systems receive files from customers over email, web forms, and mobile apps. The file types are unpredictable: PDFs, screenshots, log files, spreadsheets, recordings, archives. Many support tools try to render all attachments as img elements and fall back to a broken icon for anything that is not a browser-renderable image format.
A second failure mode is URL expiration. Most support platforms store attachments in object storage with signed URLs that expire after a period. If an agent revisits an old ticket, attachment URLs from 90+ days ago may be expired, producing 404 responses for every thumbnail.
Both failure modes produce the same broken icon. A type-aware placeholder replaces the broken icon with useful information.
Type mapping
File type to placeholder color and label mapping
A small mapping from MIME type or file extension to placeholder URL provides the foundation for type-aware attachment previews. Use distinct colors that agents can learn to recognize at a glance: red for documents, green for spreadsheets, blue for PDFs, orange for videos, yellow for archives.
const ATTACHMENT_PLACEHOLDERS: Record<string, string> = {
'application/pdf':
'https://fallback.pics/api/v1/120x120/EF4444/FFFFFF?text=PDF',
'application/msword':
'https://fallback.pics/api/v1/120x120/3B82F6/FFFFFF?text=DOC',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
'https://fallback.pics/api/v1/120x120/3B82F6/FFFFFF?text=DOCX',
'application/vnd.ms-excel':
'https://fallback.pics/api/v1/120x120/10B981/FFFFFF?text=XLS',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
'https://fallback.pics/api/v1/120x120/10B981/FFFFFF?text=XLSX',
'text/csv':
'https://fallback.pics/api/v1/120x120/10B981/FFFFFF?text=CSV',
'video/mp4':
'https://fallback.pics/api/v1/120x120/F97316/FFFFFF?text=MP4',
'application/zip':
'https://fallback.pics/api/v1/120x120/8B5CF6/FFFFFF?text=ZIP',
'text/plain':
'https://fallback.pics/api/v1/120x120/71717A/FFFFFF?text=TXT',
default:
'https://fallback.pics/api/v1/120x120/71717A/FFFFFF?text=FILE',
};
function attachmentPlaceholder(mimeType: string): string {
return ATTACHMENT_PLACEHOLDERS[mimeType] ?? ATTACHMENT_PLACEHOLDERS.default;
} Render pattern
AttachmentPreview component for support UIs
The component logic is: if the attachment is an image MIME type, render with src and an onerror fallback. If it is any other type, render the type placeholder directly as the src. Never try to render a PDF or DOCX as an img src.
interface AttachmentPreviewProps {
url: string;
mimeType: string;
filename: string;
size?: number;
}
export function AttachmentPreview({
url,
mimeType,
filename,
size = 120,
}: AttachmentPreviewProps) {
const isImage = mimeType.startsWith('image/');
const placeholder = attachmentPlaceholder(mimeType);
return (
<a href={url} target="_blank" rel="noopener noreferrer" title={filename}>
<img
src={isImage ? url : placeholder}
width={size}
height={size}
alt={filename}
onError={
isImage
? (e) => {
e.currentTarget.onerror = null;
e.currentTarget.src = placeholder;
}
: undefined
}
/>
</a>
);
} Expired URLs
Handle expired signed storage URLs in old tickets
When an agent opens an old ticket, the attachment URL may have expired. Rather than showing broken icons throughout the conversation, detect the 404 at component mount and replace with a type placeholder proactively.
A HEAD request at mount time catches expired URLs before the img element tries to load them, preventing the brief broken-icon flash that onerror-only approaches produce.
function useAttachmentSrc(url: string, mimeType: string) {
const [src, setSrc] = useState(
mimeType.startsWith('image/') ? url : attachmentPlaceholder(mimeType)
);
useEffect(() => {
if (!mimeType.startsWith('image/')) return;
fetch(url, { method: 'HEAD' }).then((res) => {
if (!res.ok) setSrc(attachmentPlaceholder(mimeType));
});
}, [url, mimeType]);
return src;
} Zendesk / Intercom
Custom attachment rendering in Zendesk and Intercom apps
Both Zendesk Apps Framework and Intercom App Kit allow custom rendering of ticket attachment areas. If you are building a support sidebar app, you can override the default attachment preview with your own component and apply the type-aware placeholder logic.
For Zendesk, use the ticket.comment.attachments API to get MIME types and URLs. For Intercom, the conversation.parts[].attachments array provides the same data. Both give you enough information to apply the file type mapping.
Key takeaways
What to standardize before shipping
- Never render non-image MIME types as img src—use a file type placeholder directly instead of attempting to render and catching the error.
- Map MIME types to distinct colored placeholder images so support agents recognize file formats without reading the filename.
- Detect expired signed storage URLs with a HEAD request at component mount to avoid brief broken-icon flashes in old tickets.
- Both Zendesk and Intercom provide MIME type data in their attachment APIs, enabling type-aware placeholder rendering in sidebar apps.
- Keep the onerror handler active for image MIME types to handle CDN failures and encoding errors.
Production fallback layer
Use fallback.pics anywhere an image URL is accepted.
Start with one deterministic URL and standardize fallback behavior across your design system.