jackwener/OpenCLI · error · CommandExecutionError

Failed to fetch Instagram media metadata

Error message

Failed to fetch Instagram media metadata

What it means

normalizeFetchResult validates the result returned from an in-page script that fetches Instagram media metadata. If unwrapEvaluateResult yields null, a non-object, or an array, the page script failed to produce a usable result envelope, so this CommandExecutionError is thrown instead of continuing with an unusable value. It signals the metadata fetch itself broke, not that Instagram reported a logical failure (that is handled by handleFetchFailure).

Source

Thrown at clis/instagram/download.js:304

      return {
        ok: true,
        shortcode: media.code,
        owner: media?.user?.username || '',
        items,
      };
    })()
  `;
}
function ensurePage(page) {
    if (!page)
        throw new CommandExecutionError('Browser session required');
    return page;
}
function normalizeFetchResult(result) {
    const unwrapped = unwrapEvaluateResult(result);
    if (!unwrapped || typeof unwrapped !== 'object' || Array.isArray(unwrapped)) {
        throw new CommandExecutionError('Failed to fetch Instagram media metadata');
    }
    if (typeof unwrapped.ok !== 'boolean') {
        throw new CommandExecutionError('Instagram media metadata returned malformed result');
    }
    return unwrapped;
}
function handleFetchFailure(result) {
    const message = result.error || 'Instagram media fetch failed';
    if (result.errorCode === 'AUTH_REQUIRED') {
        throw new AuthRequiredError('instagram.com', message);
    }
    if (result.errorCode === 'RATE_LIMITED') {
        throw new CliError('RATE_LIMITED', message, 'Wait a few minutes and retry, or switch to a browser session with a warmer Instagram login state.', EXIT_CODES.TEMPFAIL);
    }
    if (result.errorCode === 'PRIVATE_OR_UNAVAILABLE') {
        throw new CommandExecutionError(message, 'Open the post in a logged-in browser session and retry');
    }
    throw new CommandExecutionError(message);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check the browser session is valid and logged in, then re-run the instagram download command
  2. Retry after ensuring no concurrent navigation happens while the command runs
  3. Update the CLI, since Instagram page/API changes often break the injected fetch script
  4. Wrap or patch buildInstagramFetchScript to always return an {ok:false,error} envelope instead of throwing

Example fix

// before (injected script can throw, evaluate yields null)
const media = await fetchMetadata();
// after (always return an envelope)
try { const media = await fetchMetadata(); return { ok: true, media }; }
catch (e) { return { ok: false, errorCode: 'COMMAND_EXEC', error: String(e) }; }
Defensive patterns

Strategy: try-catch

Validate before calling

if (!page) throw new Error('Browser session required before running instagram download');

Type guard

function isFetchEnvelope(r) {
  return r !== null && typeof r === 'object' && !Array.isArray(r);
}

Try / catch

try {
  const result = normalizeFetchResult(raw);
} catch (e) {
  if (String(e.message).includes('Failed to fetch Instagram media metadata')) {
    // restart browser session and retry once
  } else throw e;
}

Prevention

When it happens

Trigger: browserPage.evaluate() returns null/undefined (page script threw and the wrapper swallowed it), returns a JSON scalar (string/number), or returns an array instead of an {ok, items, ...} object; typically when the page navigated away, the evaluate script was blocked, or the injected script errored before building the result.

Common situations: Instagram served a login redirect so the in-page fetch never ran; a page reload or navigation raced the evaluate call; a CSP change or Instagram DOM/API change made the injected script throw; the browser session was closed mid-call.

Related errors


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