jackwener/OpenCLI · error · CommandExecutionError

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

Error message

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

What it means

clickAction runs buildClickActionJs to find and click one of the given labeled buttons in the Instagram reel flow. If the evaluate result is not ok, it throws CommandExecutionError with the joined label list. It means none of the requested buttons existed or was clickable at that point in the flow.

Source

Thrown at clis/instagram/reel.js:227

        const result = await page.evaluate(buildInspectUploadStageJs());
        lastDetail = String(result?.detail || '').trim();
        if (result?.state === 'preview')
            return;
        if (result?.state === 'failed') {
            throw new CommandExecutionError('Instagram reel upload failed', result.detail ? `Instagram rejected the reel upload: ${result.detail}` : 'Instagram rejected the reel upload before the preview stage');
        }
        if (attempt < maxWaitSeconds * 2 - 1)
            await page.wait({ time: 0.5 });
    }
    await page.screenshot({ path: '/tmp/instagram_reel_preview_debug.png' });
    throw new CommandExecutionError('Instagram reel preview did not appear after upload', lastDetail
        ? `Inspect /tmp/instagram_reel_preview_debug.png. Last visible dialog text: ${lastDetail}`
        : 'Inspect /tmp/instagram_reel_preview_debug.png for the upload state');
}
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 clickActionMaybe(page, labels, scope = 'any') {
    const result = await page.evaluate(buildClickActionJs(labels, scope));
    return !!result?.ok;
}
function buildInspectReelStageJs() {
    return `
    (() => {
      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;

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check what the page actually shows (screenshot/DOM) — the flow likely isn't on the expected step.
  2. Add the current Instagram label variants to the labels array, including the account's language (e.g. ['Next','Next','Next']).
  3. Wait for the target stage (waitForReelStage) before calling clickAction so the button exists.
  4. Use clickActionMaybe with your own retry loop for buttons that appear conditionally (e.g. 'Save draft' prompt).
  5. Update buildClickActionJs selectors if Instagram changed the button DOM structure.

Example fix

// before
await clickAction(page, ['Next']);
// after
await waitForReelStage(page, 'caption');
await clickActionMaybe(page, ['Save draft']) || null;
await clickAction(page, ['Next', 'Next', 'Next']);
Defensive patterns

Strategy: validation

Validate before calling

// Wait for the stage first, then verify a button exists before clicking
await waitForReelStage(page, 'caption');
const hasBtn = await page.evaluate(buildClickActionJs(labels, scope));
if (!hasBtn?.ok) throw new Error(`Skipping click: none of [${labels}] present — check current step`);

Type guard

function isClickOk(r) {
  return !!r && typeof r === 'object' && r.ok === true &&
    (r.label === undefined || typeof r.label === 'string');
}

Try / catch

try {
  return await clickAction(page, labels, scope);
} catch (err) {
  if (String(err.message).startsWith('Instagram action button not found')) {
    await page.screenshot({ path: '/tmp/ig_click_miss.png' });
    throw new Error(`${err.message} — see /tmp/ig_click_miss.png for actual page state`);
  }
  throw err;
}

Prevention

When it happens

Trigger: clickAction(page, labels, scope) is called (e.g. 'Next', 'Share') and buildClickActionJs returns {ok:false} because no visible/enabled button matching any label (within scope) is present in the DOM.

Common situations: Instagram renamed/translated buttons (locale-dependent labels); the flow is on a different step than expected (previous stage skipped or delayed); an interstitial dialog (rate-limit, error, save-draft prompt) covers the button; the wrong scope ('any' vs specific dialog) misses the button's container.

Related errors


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