On this page

"Media expired" or a broken attachment in the inbox almost always affects Instagram or Messenger conversations, not WhatsApp, because of how Meta delivers each channel's media differently. Once it happens, the original file cannot be recovered from anywhere; the fix is prevention, catching it with a permanent copy before the signed URL's expiry lapses.
Symptom
An image, video, or other attachment in a conversation renders as a placeholder reading "Media expired" instead of the actual file, or fails to load with no content shown at all. This is seen almost exclusively on Instagram DM and Messenger conversations; a genuine WhatsApp attachment failing to load this way is rare, since WhatsApp media is handled through a different, more durable mechanism from the start. The message itself, its text, sender, and timestamp, remains fully intact in the conversation; only the attachment display is affected.
Why it happens
Meta delivers media very differently across its channels, and the difference is the entire cause of this symptom. WhatsApp's Cloud API delivers media by a stable media ID, which VGraple CRM downloads and re-hosts to permanent object storage at the moment the message is received, so the original bytes are captured durably almost immediately and do not depend on any URL staying valid later. Instagram DM and Messenger media instead arrives referenced by a signed CDN URL, hosted on cdninstagram.com, fbcdn.net, or a related Meta domain, with an expiry timestamp baked directly into the URL's signature. Re-hosting that media to permanent storage happens as a background, fire-and-forget process at the time the message is ingested; if that process encounters a transient network or storage error and does not complete before the signed URL's own expiry lapses, typically measured in days, the original bytes become permanently unfetchable from Meta's side, and there is nothing left to recover from.

A second, related cause is a signed URL rendered directly rather than through a permanent copy: a carousel card image or a repeated preview can display straight from Meta's CDN URL the first time it is viewed, working correctly at that moment, and then stop rendering later purely because the signature's fixed expiry has since passed, even though nothing about the message or the conversation changed in between.
Fix
- Confirm whether the affected conversation is Instagram, Messenger, or WhatsApp. This determines whether recovery is even possible; WhatsApp attachments failing to load point to a different, less common cause and are worth reporting separately.
- For an Instagram or Messenger attachment showing "Media expired," check when the message originally arrived. If it has been more than roughly 14 to 30 days, the original CDN signature has almost certainly lapsed and the media cannot be recovered.
- For a recently received attachment showing this, wait and refresh. The background re-hosting process retries automatically on a schedule and often resolves a transient failure within its next pass, without any action needed.
- If the sender still has the original file, ask them to resend it. This is the only reliable recovery path once a signed URL has genuinely expired; there is no server-side way to reconstruct media Meta itself will no longer serve.
- For a WhatsApp attachment specifically failing to load, this is unusual enough to be worth checking channel health for a broader token or connectivity issue, rather than treating it as the same expected-and-common Instagram/Messenger case.
How VGraple CRM handles it automatically
Every Instagram DM and Messenger message carrying media is queued for background re-hosting to permanent object storage the moment it is ingested, downloading the original bytes from Meta's signed CDN URL and storing a stable copy under VGraple CRM's own control, independent of any expiry. This runs sequentially and retries on a schedule so a transient failure at ingest time gets another chance before the signed URL's own expiry closes the window for good; newer messages are retried first, since their signed URLs are the ones still most likely to resolve. A dedicated media proxy also serves display requests for both permanently re-hosted files and, where a stable copy is not yet available, the original signed URL directly, restricted strictly to Meta's own known media hosts and to authenticated, rate-limited requests, so the inbox never has to trust or forward an arbitrary URL.
Separately, older messages stored before this repair pipeline existed can carry a placeholder body text rather than genuine media (an internal marker like "[ig_post]" from an earlier version of the attachment handling); a background job rewrites these historical rows to a plain, human-readable sentence describing what was shared, so an old conversation reads sensibly even where the original attachment itself could never be recovered.
Example
A customer sends a product photo through Instagram DM at 2 PM. VGraple CRM's re-hosting job attempts to download it within minutes but hits a brief storage outage and the attempt fails silently in the background. The next scheduled retry, a few hours later, succeeds, and the image displays normally in the inbox from then on with no visible interruption to the agent handling the conversation, since the retry completed well inside the CDN URL's expiry window.
Prevention
There is no configuration on the business's side that prevents Meta's signed URLs from expiring, since that expiry is set entirely by Meta's own CDN infrastructure for Instagram and Messenger media. The only meaningful prevention is on VGraple CRM's side, keeping the background re-hosting pipeline healthy so the permanent copy completes well within the expiry window, which is already the default, always-on behaviour rather than something to configure. For anyone integrating against the API directly and handling media independently, downloading and storing a permanent copy of any inbound media as soon as it arrives, rather than storing and later trying to re-fetch the original signed URL, avoids this failure mode entirely in a custom integration too.
Why does this only really affect Instagram and Messenger?
WhatsApp's Cloud API was designed from the start around stable media IDs specifically because WhatsApp media, unlike a social CDN URL meant for browser display, is expected to be fetched and stored reliably by the business receiving it. Instagram and Messenger's DM media delivery, by contrast, reuses the same signed-URL mechanism Meta uses for ordinary social media content display, optimised for a browser rendering a post once, not for a business archiving a customer conversation indefinitely. That mismatch, a mechanism built for transient display being used to carry data a CRM needs to keep, is the entire reason this symptom exists on those two channels specifically and is why VGraple CRM's re-hosting pipeline exists as a deliberate correction rather than a Meta-provided feature.