← back to Marketing Command Center
instagram: poll media container status until FINISHED before publish — fixes 'Media ID is not available' (Meta processes images async)
c1d7a1d3838c782e8a78f7e0be41ac1ed0ae1a2e · 2026-07-17 09:58:38 -0700 · Steve Abrams
Files touched
M modules/channels/index.js
Diff
commit c1d7a1d3838c782e8a78f7e0be41ac1ed0ae1a2e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Jul 17 09:58:38 2026 -0700
instagram: poll media container status until FINISHED before publish — fixes 'Media ID is not available' (Meta processes images async)
---
modules/channels/index.js | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/modules/channels/index.js b/modules/channels/index.js
index 2d73b3f..f535259 100644
--- a/modules/channels/index.js
+++ b/modules/channels/index.js
@@ -412,6 +412,17 @@ async function postInstagram(content, opts = {}) {
});
const cj = await create.json().catch(() => ({}));
if (!create.ok || !cj.id) { results.push({ igId: t.igId, name: t.name, ok: false, error: cj.error?.message || 'media create failed' }); continue; }
+ // Meta processes the image container ASYNC — publishing before it's FINISHED throws
+ // "Media ID is not available". Poll status_code until FINISHED (or ERROR/timeout).
+ let ready = false;
+ for (let i = 0; i < 12; i++) {
+ await new Promise(r => setTimeout(r, i === 0 ? 1500 : 2500));
+ const s = await fetch(`${GRAPH}/${cj.id}?fields=status_code&access_token=${encodeURIComponent(t.token)}`);
+ const sj = await s.json().catch(() => ({}));
+ if (sj.status_code === 'FINISHED') { ready = true; break; }
+ if (sj.status_code === 'ERROR' || sj.status_code === 'EXPIRED') { break; }
+ }
+ if (!ready) { results.push({ igId: t.igId, name: t.name, ok: false, error: 'media container not ready (still processing or errored)' }); continue; }
const pub = await fetch(`${GRAPH}/${t.igId}/media_publish`, {
method: 'POST', headers: { 'content-type': 'application/json' },
body: JSON.stringify({ creation_id: cj.id, access_token: t.token }),
← 47459ec cc-import: stage gated FM-client → Constant Contact import (
·
back to Marketing Command Center
·
chore: lint, refactor (drop dead env()), v1.4.0 (session clo d77d6ee →