Skip to content

Engineering

Fix: Instagram "Media ID is not available" on media_publish

Meta's Instagram Content Publishing API returns "Media ID is not available" (error code 100) when a `media_publish` call arrives before the container it references has finished processing. This is a real defect SkedCast shipped and fixed (PR #500) — the actual container-readiness bug, not a hypothetical.

All articles

By The SkedCast Team · Updated · 6 min read

Key takeaways

  • Instagram's Content Publishing API is URL ingestion, not a byte upload — POST /{ig-user}/media returns a container id the moment the request is ACCEPTED, before Meta has fetched or assembled anything.
  • Meta requires polling GET /{container-id}?fields=status_code until it reads FINISHED before calling media_publish; publishing early returns exactly "Media ID is not available" (code 100).
  • The bug: SkedCast's adapter did poll for readiness, but every call site gated the wait on `item.isVideo` — so only video posts ever waited, and every other shape (single image, image story, every carousel child, and the carousel parent itself) published unguarded.
  • The carousel PARENT is the likeliest of all of them to still be IN_PROGRESS at publish time, because Meta has to assemble it out of N already-uploaded children — and nothing had ever waited for it.

What two production posts actually did

Two posts on a real, live SkedCast-connected Instagram account died on 2026-09-07 with Meta's "Media ID is not available" at media_publish: one target was a single image, the other a five-image carousel. The media itself was blameless — all five carousel cards had transcoded cleanly to 1080×1350 JPEG at 105–140 KB each — and the same account had already published a single image at 00:00Z and a video at 15:01Z on the same day without issue.

That last detail is the tell. The one shape that never failed was the one shape the adapter had always waited for.

Why Instagram publishing needs a readiness poll at all

Instagram's Content Publishing API never receives file bytes from a third-party app directly — SkedCast hands Meta a URL, and POST /{ig-user}/media returns a container id the instant the request is ACCEPTED, well before Meta has actually fetched or processed anything from that URL. Meta's documented contract is to poll GET /{container-id}?fields=status_code until it reads FINISHED, and only then call media_publish — publishing against a container that is still IN_PROGRESS is refused with error code 100 and exactly the message "Media ID is not available".

SkedCast's adapter did implement that poll. The defect was narrower and easy to miss: every call site that decided whether to wait was gated on item.isVideo, so the only content shape that ever actually waited was the only shape that had never failed.

Instagram "Media ID is not available": what was unguarded, and the fix

Left unguarded: the single feed image, the image story, every carousel child, and — the case nothing had ever waited for — the carousel PARENT, which Meta has to assemble out of N already-processed children and is therefore the single most likely container of all of them to still be IN_PROGRESS when media_publish arrives.

The fix (PR #500) made the readiness poll unconditional across every call site instead of video-only, and added one hardening rule discovered while writing it: a container that already reads PUBLISHED counts as ready too, since it is a terminal state and waiting for it to further become FINISHED would hang forever on a container Meta has already moved past.

The general lesson for anyone integrating this API

If your integration polls container status only for video, and you have not seen this error on an image post yet, that is very likely luck rather than correctness — images typically process faster than video, so the readiness race is narrower but not absent. Poll every container to FINISHED (or PUBLISHED) before calling media_publish, with no exception for content type, and remember that a carousel parent is its own container with its own readiness state, separate from its children's.

instagrammeta graph apimedia_publishengineering postmortem

FAQ

What does Instagram's "Media ID is not available" error (code 100) actually mean?
It means media_publish was called against a container that Meta has not finished processing yet — the container exists (it has an id) but its status_code is not FINISHED, so Meta refuses to publish it and returns error code 100 with that message.
Does this error only happen with video posts?
No. It is often assumed to be video-only because video containers take visibly longer to process, but a single image, an image story, and — especially — a carousel's parent container can all still be IN_PROGRESS at publish time under the wrong timing.
How do I check if an Instagram media container is ready to publish?
Call GET /{container-id}?fields=status_code and check for FINISHED (or PUBLISHED, which is also terminal) before calling media_publish against that container id. Poll on an interval rather than a single check, since processing time varies.
Why would a carousel be more likely to fail than a single image?
A carousel's parent container is assembled out of every child container after each child has already processed, which makes the parent's own readiness a separate, following event — and the one most integrations forget to wait for since attention naturally goes to the children.
Is this a rate-limit or authentication problem?
No — it is purely a timing/readiness issue local to one container. It is unrelated to OAuth token validity or Instagram's publishing rate limits, and re-authenticating will not fix it.
Will retrying the same media_publish call fix it?
It can appear to, purely by luck, if enough time has passed between the failed attempt and the retry for the container to finish processing on its own — but the reliable fix is to poll status_code to a terminal state before ever calling media_publish, not to retry blind.

Ready to broadcast everywhere?

Sign up free — no credit card. You land on the Free plan, and you can start a one-time 7-day Studio trial from your workspace whenever you are ready. Connect your first accounts, import a batch, and watch one post fan out across every platform.