From a88e96adf5afedd706cd0f5553b8a4b6dd44e1f3 Mon Sep 17 00:00:00 2001 From: Marcio Bevervanso Date: Mon, 8 Jun 2026 14:21:18 -0300 Subject: [PATCH] fix: fall back to Facebook-only when ad account can't use the page's Instagram Meta rejects the whole ad creative with error 200/1815199 when the ad account isn't authorized (in Business Manager) to use the Instagram account linked to the chosen page. Picking a different page in the new selector doesn't help if that page's IG is also unshared. Now, when the creative fails for that specific reason, we retry without instagram_actor_id so the ad still publishes on Facebook, and the modal explains why Instagram was dropped and how to enable it. createFullCampaign gets the same fallback for free. Co-Authored-By: Claude Opus 4.8 --- src/components/dashboard/AddAdModal.tsx | 9 ++++ src/lib/mcp/tools.ts | 58 +++++++++++++++++-------- 2 files changed, 49 insertions(+), 18 deletions(-) diff --git a/src/components/dashboard/AddAdModal.tsx b/src/components/dashboard/AddAdModal.tsx index ed071bb..087a2c3 100644 --- a/src/components/dashboard/AddAdModal.tsx +++ b/src/components/dashboard/AddAdModal.tsx @@ -80,6 +80,7 @@ export function AddAdModal({ const [publishing, setPublishing] = useState(false); const [error, setError] = useState(null); const [done, setDone] = useState(false); + const [instagramDropped, setInstagramDropped] = useState(false); useEffect(() => { let cancelled = false; @@ -271,6 +272,7 @@ export function AddAdModal({ return; } + setInstagramDropped(Boolean(data.data?.instagram_dropped)); setDone(true); onCreated(); } catch (err) { @@ -301,6 +303,13 @@ export function AddAdModal({

Ele foi criado como Pausado — ative-o no Ads Manager (ou na tabela) quando estiver pronto.

+ {instagramDropped && ( +
+ ⚠️ Publicamos só no Facebook: a conta de anúncios ainda não tem permissão pra usar + {selectedInstagramAccount ? <> a conta @{selectedInstagramAccount.username} : ' a conta do Instagram'} desta página. + Para ativar o Instagram, vincule a conta no Business Manager (Configurações do Negócio → Contas do Instagram → Atribuir conta de anúncios) e republique. +
+ )} ) : ( diff --git a/src/lib/mcp/tools.ts b/src/lib/mcp/tools.ts index 4876503..eca3009 100644 --- a/src/lib/mcp/tools.ts +++ b/src/lib/mcp/tools.ts @@ -608,26 +608,30 @@ export async function addAdToAdSet(client: Client, params: AddAdToAdSetParams) { // the most broadly compatible across placements. const primaryImageHash = imageHashes[0]; - let creative; - if (params.is_whatsapp) { - creative = await createWhatsappAdCreative(client, { + // Monta o criativo com (ou sem) o Instagram. Quando a conta de anúncios não + // tem permissão pra usar a conta de IG vinculada à página, a Meta recusa o + // criativo inteiro (erro 200 / subcode 1815199). Nesse caso refazemos o + // criativo só com o Facebook, em vez de barrar a publicação. + const buildCreative = (instagramActorId?: string) => { + if (params.is_whatsapp) { + return createWhatsappAdCreative(client, { + name: creativeName, + page_id: params.page_id, + instagram_actor_id: instagramActorId, + image_hash: primaryImageHash, + message: params.primary_text, + headline: params.headline, + description: params.description, + link: params.link, + whatsapp_link: params.whatsapp_link, + whatsapp_phone_number: params.whatsapp_phone_number, + ad_account_id: params.ad_account_id, + }); + } + return createAdCreative(client, { name: creativeName, page_id: params.page_id, - instagram_actor_id: params.instagram_actor_id, - image_hash: primaryImageHash, - message: params.primary_text, - headline: params.headline, - description: params.description, - link: params.link, - whatsapp_link: params.whatsapp_link, - whatsapp_phone_number: params.whatsapp_phone_number, - ad_account_id: params.ad_account_id, - }); - } else { - creative = await createAdCreative(client, { - name: creativeName, - page_id: params.page_id, - instagram_actor_id: params.instagram_actor_id, + instagram_actor_id: instagramActorId, image_hash: primaryImageHash, link: params.link, message: params.primary_text, @@ -636,6 +640,23 @@ export async function addAdToAdSet(client: Client, params: AddAdToAdSetParams) { call_to_action_type: params.cta, ad_account_id: params.ad_account_id, }); + }; + + // 1815199: "A conta de anúncios não tem acesso a esta conta do Instagram". + const isInstagramPermissionError = (err: unknown) => + err instanceof Error && /1815199/.test(err.message); + + let creative; + let instagramDropped = false; + try { + creative = await buildCreative(params.instagram_actor_id); + } catch (err) { + if (params.instagram_actor_id && isInstagramPermissionError(err)) { + creative = await buildCreative(undefined); + instagramDropped = true; + } else { + throw err; + } } const creativeId = (creative as any)?.id; @@ -659,6 +680,7 @@ export async function addAdToAdSet(client: Client, params: AddAdToAdSetParams) { adset_id: params.adset_id, creative_id: creativeId, ad_id: adId, + instagram_dropped: instagramDropped, }; }