Explorar el Código

Fix Instagram #9007: poll container status before publishing

Instagram's two-step Container API requires the media to reach
FINISHED status before media_publish is called. Publishing immediately
after container creation causes error #9007 (Media ID is not available)
because Instagram hasn't finished processing the image yet.

waitForContainerReady() polls GET /{creation_id}?fields=status_code
every 3 seconds for up to 12 attempts (36s total). Returns on FINISHED,
throws with a clear message on ERROR, EXPIRED, or timeout.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Benjamin Harris hace 3 semanas
padre
commit
be2e258ae7
Se han modificado 1 ficheros con 23 adiciones y 1 borrados
  1. 23 1
      services/instagram/index.js

+ 23 - 1
services/instagram/index.js

@@ -29,6 +29,23 @@ function resolveInstagramMediaUrl(url) {
   return url;
 }
 
+// Instagram's two-step publish requires the container to reach FINISHED status before
+// calling media_publish. Poll up to maxAttempts × intervalMs ms before giving up.
+async function waitForContainerReady(creationId, accessToken, maxAttempts = 12, intervalMs = 3000) {
+  for (let i = 0; i < maxAttempts; i++) {
+    const res = await axios.get(`${GRAPH_API}/${creationId}`, {
+      params: { fields: 'status_code,status', access_token: accessToken },
+    });
+    const { status_code, status } = res.data;
+    if (status_code === 'FINISHED') return;
+    if (status_code === 'ERROR') throw new Error(`Instagram media processing failed: ${status || 'unknown error'}`);
+    if (status_code === 'EXPIRED') throw new Error('Instagram media container expired before it could be published');
+    // IN_PROGRESS — wait and retry
+    await new Promise((r) => setTimeout(r, intervalMs));
+  }
+  throw new Error('Instagram media container did not finish processing in time (36s). Try again or use a faster-loading image URL.');
+}
+
 class InstagramService extends BasePlatformService {
   constructor() {
     super('instagram');
@@ -172,10 +189,15 @@ class InstagramService extends BasePlatformService {
         null,
         { params: containerParams }
       );
+      const creationId = containerRes.data.id;
+
+      // Wait for Instagram to finish processing the media before publishing
+      await waitForContainerReady(creationId, account.accessToken);
+
       const publishRes = await axios.post(
         `${GRAPH_API}/${account.id}/media_publish`,
         null,
-        { params: { creation_id: containerRes.data.id, access_token: account.accessToken } }
+        { params: { creation_id: creationId, access_token: account.accessToken } }
       );
       const postId = publishRes.data.id;