jackwener/OpenCLI · error · CommandExecutionError

Instagram action button not found: ${labels.join(' / ')}

Error message

Instagram action button not found: ${labels.join(' / ')}

What it means

clickAction evaluates generated JS that locates and clicks one of the labeled action buttons (e.g. Next/Share) within the composer. If the script reports not-ok, meaning no matching button was found in the given scope, the library throws with the joined label list. It marks a step of the publish wizard that could not be advanced.

Source

Thrown at clis/instagram/post.js:856

        for (const node of nodes) {
          const text = (node.textContent || '').replace(/\\s+/g, ' ').trim();
          const aria = (node.getAttribute?.('aria-label') || '').replace(/\\s+/g, ' ').trim();
          if (!text && !aria) continue;
          if (!labels.includes(text) && !labels.includes(aria)) continue;
          if (node instanceof HTMLElement && isVisible(node) && node.getAttribute('aria-disabled') !== 'true') {
            node.click();
            return { ok: true, label: text || aria };
          }
        }
      }
      return { ok: false };
    })(${JSON.stringify(labels)}, ${JSON.stringify(scope)})
  `;
}
async function clickAction(page, labels, scope = 'any') {
    const result = await page.evaluate(buildClickActionJs(labels, scope));
    if (!result?.ok) {
        throw new CommandExecutionError(`Instagram action button not found: ${labels.join(' / ')}`);
    }
    return result.label || labels[0];
}
async function clickVisibleShareRetry(page) {
    const result = await page.evaluate(`
    (() => {
      const isVisible = (el) => {
        if (!(el instanceof HTMLElement)) return false;
        const style = window.getComputedStyle(el);
        const rect = el.getBoundingClientRect();
        return style.display !== 'none'
          && style.visibility !== 'hidden'
          && rect.width > 0
          && rect.height > 0;
      };

      const dialogs = Array.from(document.querySelectorAll('[role="dialog"]')).filter((el) => isVisible(el));
      for (const dialog of dialogs) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry with scope 'any' so all composer regions are searched for the button
  2. Screenshot the page to see which step of the composer is actually displayed
  3. Update the CLI in case Instagram changed button labels or markup
  4. Wait briefly before the action so the current step finishes rendering
  5. Dismiss any overlays/dialogs (e.g. 'Save login info' prompts) blocking the wizard

Example fix

// before
await clickAction(page, ['Next'], 'editor');
// after
await page.wait({ time: 1 });
await clickAction(page, ['Next', 'Next'], 'any'); // broaden labels + scope
Defensive patterns

Strategy: retry

Validate before calling

const btn = await page.evaluate(() =>
  ['Next', 'Share'].some(l => [...document.querySelectorAll('button, [role=button]')].some(b => b.textContent.trim().includes(l)))
);
if (!btn) await page.wait({ time: 1 });

Try / catch

try {
  await clickAction(page, ['Next'], 'editor');
} catch (e) {
  if (String(e.message).startsWith('Instagram action button not found')) {
    await page.wait({ time: 1 });
    await clickAction(page, ['Next'], 'any'); // broaden scope and retry
  } else throw e;
}

Prevention

When it happens

Trigger: Called from executeUiInstagramPost or advanceToCaptionEditor; the page.evaluate of buildClickActionJs returns { ok:false } because no button matching any of the labels exists in the searched scope.

Common situations: Instagram redesign renaming/moving buttons, wrong scope ('editor' vs 'any') excluding the button, composer still on a prior step, or a modal/overlay intercepting clicks so the button search misses.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/af53a4574356f6db. Report an issue: GitHub.