jackwener/OpenCLI · error · CommandExecutionError

Discord search returned malformed browser payload.

Error message

Discord search returned malformed browser payload.

What it means

After running the search scrape script, the command expects searchState with an items array. If the injected script returned null/undefined or an object without an items array, it throws CommandExecutionError('Discord search returned malformed browser payload.'). This guards against the in-page scrape failing silently or returning an unexpected shape.

Source

Thrown at clis/discord-app/search.js:54

        const resultNodes = document.querySelectorAll('[class*="searchResult_"], [id*="search-result"]');
        
        resultNodes.forEach((node, i) => {
          const author = node.querySelector('[class*="username"]')?.textContent?.trim() || '—';
          const content = node.querySelector('[id^="message-content-"], [class*="messageContent"]')?.textContent?.trim() || node.textContent?.trim();
          items.push({
            Index: i + 1,
            Author: author,
            Message: (content || '').substring(0, 200),
          });
        });
        
        const bodyText = document.body?.innerText || document.body?.textContent || '';
        const empty = /no results|no messages match|没有结果|无结果/i.test(bodyText);
        return { items, empty };
      })()
    `);
        if (!searchState || !Array.isArray(searchState.items)) {
            throw new CommandExecutionError('Discord search returned malformed browser payload.');
        }
        const results = searchState.items;
        // Close search
        await page.pressKey('Escape');
        if (results.length === 0) {
            if (!searchState.empty) {
                throw new CommandExecutionError('Discord search result selector returned no rows and no explicit empty-state marker.');
            }
            throw new EmptyResultError('discord-app search', `No results for "${query}".`);
        }
        return results;
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the search command — a transient page re-render often resolves it.
  2. Ensure the Discord tab/page is stable (no navigation, not minimized to the point scripts are throttled) during search.
  3. Add/increase a wait after typing the query so results render before the scrape runs.
  4. Update the scrape script to the current DOM if Discord changed the results container.

Example fix

// before
const searchState = await page.evaluate(scrapeScript);
// after: tolerate transient failure with a retry
let searchState = await page.evaluate(scrapeScript);
if (!searchState) { await page.wait(1); searchState = await page.evaluate(scrapeScript); }
Defensive patterns

Strategy: retry

Validate before calling

const ok = await page.evaluate(`!document.hidden && document.readyState === 'complete'`);
if (!ok) await page.wait(1);

Type guard

function isWellFormedSearchState(s) { return s && Array.isArray(s.items) && typeof s.empty === 'boolean'; }

Try / catch

try {
  await run('discord-app search --query=...');
} catch (e) {
  if (/malformed browser payload/.test(e.message)) {
    await page.wait(1.5); // let SPA settle
    await run('discord-app search --query=...');
  }
}

Prevention

When it happens

Trigger: The page.evaluate scrape script threw or returned undefined (page navigated mid-eval, context destroyed), the search results pane never rendered so the script bailed, or a Discord DOM change broke the script's return shape so items is missing.

Common situations: SPA re-render/unmount of the results panel during evaluation; evaluate called on a stale or closed frame; Discord update removing the container the script reads; heavy page making the script time out.

Understand the failure class

Related errors


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