From 21397240509aa4746cbd898299c80f336c19d5c8 Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Tue, 1 Sep 2026 17:44:35 -0400 Subject: [PATCH] instagram: do not believe a refusal the account contradicts @menuband.app was never blocked from publishing. It was publishing fine and being told it had failed. `media_publish` can post the reel and still answer 400. That is what happened 33 times: each hourly run reported "Cannot Create Media / Create media fail, please try to re-create media", each one put another copy of 95-saucer on the grid, and none of them reached the ledger. The account ended up carrying 33 more posts than its own record knew about -- the 79-vs-46 gap that turned up during the grid reset and got written off as a stale ledger. Read as a wall of identical failures, it looked like an account-level ban. It was a publishing loop with the success signal inverted. So a refusal is now checked against the account before it is believed: sample media_count either side of the call, and if it moved, the reel went up. Report success, recover the id from /media?limit=1, and let the receipt and ledger happen normally. If the count moved but the id cannot be read back, say so loudly and refuse to pretend either way -- an unledgered live post is exactly what makes the lane repost it. Proven on the account itself: 94-gramophone published first try through this same path minutes after 95-saucer's "failure" had silently published too, leaving two posts on a grid whose ledger recorded one. Claude-Session: https://claude.ai/code/session_01X62vT9M1iQXjNTF1jMcpN5 --- toolchain/instagram/ig.mjs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/toolchain/instagram/ig.mjs b/toolchain/instagram/ig.mjs index 348b4b3584..783f205877 100644 --- a/toolchain/instagram/ig.mjs +++ b/toolchain/instagram/ig.mjs @@ -339,10 +339,34 @@ async function doPost(creds) { } if (state !== "FINISHED") die(`container ended ${state} — nothing was published`); - const published = await call(api(`${creds.igUserId}/media_publish?access_token=${creds.token}`), { - method: "POST", headers: { "content-type": "application/json" }, - body: JSON.stringify({ creation_id: created.id }), - }); + // `media_publish` can post the reel AND still answer 400. @menuband.app did + // exactly that 33 times: every hourly run reported "Cannot Create Media", + // every hourly run put another copy of the same waltz on the grid, and none + // of them reached the ledger — which is why the account carried 33 more + // posts than its record knew about, and why this looked like a publishing + // ban instead of a publishing loop. So a refusal is not believed until the + // account agrees: if the media count moved, the reel went up, and the honest + // report is success with the id Meta declined to hand back. + const before = (await fetchMe(creds)).media_count; + let published; + try { + published = await call(api(`${creds.igUserId}/media_publish?access_token=${creds.token}`), { + method: "POST", headers: { "content-type": "application/json" }, + body: JSON.stringify({ creation_id: created.id }), + }); + } catch (error) { + const after = (await fetchMe(creds).catch(() => ({}))).media_count; + if (!(Number.isFinite(before) && Number.isFinite(after) && after > before)) throw error; + const recent = await call(api(`${creds.igUserId}/media?fields=id&limit=1` + + `&access_token=${creds.token}`)).catch(() => null); + const id = recent?.data?.[0]?.id; + console.log(`⚠ media_publish answered "${error.message}" but the account ` + + `went ${before} → ${after} media — the reel published anyway.`); + if (!id) throw new Error( + `published despite the error, but its media id could not be read back — ` + + `ledger it by hand before the lane reposts it`); + published = { id }; + } console.log(`✓ published · ${published.id}`); // The permalink is the one field only Meta can supply, and only after the -- 2.51.2