jackwener/OpenCLI · warning · EmptyResultError

qoder search

Error message

qoder search

What it means

Thrown by the qoder search command when the search results scrape (requireArrayResult over [role=option]/[role=menuitem] titles) yields an empty list, meaning no items matched the query. EmptyResultError includes the query in the message so the user knows what to adjust. This is an expected, data-level empty result rather than a script failure.

Source

Thrown at clis/qoder/ui.js:107

      input.dispatchEvent(new Event('change', { bubbles: true }));
      return { ok: true };
    })()`);
        if (!fillRes?.ok) throw new CommandExecutionError(fillRes?.reason || 'search type failed', '');
        await page.wait(0.8);
        const items = requireArrayResult(await evaluateQoder(page, `(() => {
      ${IS_VISIBLE_JS}
      // Search palette results: prefer [role=option], else any clickable row in the modal.
      const opts = Array.from(document.querySelectorAll('[role="option"], [role="menuitem"]')).filter(isVisible);
      const titles = opts.map((o) => {
        // Codex-style fix: text may be in per-char spans; use textContent.
        const titleEl = o.querySelector('.truncate, [class*="title"i]') || o;
        return (titleEl.textContent || '').trim().replace(/\\s+/g, ' ').slice(0, 200);
      }).filter(Boolean);
      return [...new Set(titles)];
    })()`), 'qoder search');
        try { await page.evaluate(`document.body.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));`); } catch {}
        if (!items.length) {
            throw new EmptyResultError('qoder search', `No items matched "${query}".`);
        }
        return items.slice(0, limit).map((t, i) => ({ Index: i + 1, Item: t }));
    },
});

// -------- settings --------
cli({
    site: 'qoder',
    name: 'settings',
    access: 'write',
    description: 'Click the Settings button in the Qoder sidebar.',
    domain: 'localhost',
    strategy: Strategy.UI,
    browser: true,
    args: [],
    columns: ['Status'],
    func: async (page) => {
        const res = await evaluateQoder(page, clickByTextScript(['Settings']));

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry with a broader/shorter query or check spelling.
  2. Increase the post-type wait (currently 0.8s) or poll until results appear.
  3. If results exist in the UI but aren't extracted, update the result selectors ([role=option]/[role=menuitem]) to the current markup.
  4. Escape the palette (already attempted) and rerun the search once.

Example fix

// before
await page.wait(0.8);
const items = requireArrayResult(await evaluateQoder(page, RESULTS_JS), 'qoder search');
// after
let items = [];
for (let i = 0; i < 5; i++) {
  await page.wait(0.5);
  items = requireArrayResult(await evaluateQoder(page, RESULTS_JS), 'qoder search');
  if (items.length) break;
}
Defensive patterns

Strategy: retry

Validate before calling

const query = 'my search term'.trim();
if (query.split(/\s+/).length > 6) console.warn('Long queries may match nothing; try broader terms');

Type guard

function hasItems(v) { return Array.isArray(v) && v.length > 0; }

Try / catch

try {
  const items = await search(page, query);
} catch (e) {
  if (e instanceof EmptyResultError && /qoder search/.test(e.message)) {
    return search(page, query.split(/\s+/)[0]);
  }
  throw e;
}

Prevention

When it happens

Trigger: The query genuinely matches nothing in Qoder's searchable items; the query is misspelled or too specific; results render in elements that are neither role=option nor role=menuitem after a Qoder update; results hadn't loaded yet when the scrape ran (only 0.8s wait).

Common situations: Searching a term before the search index loads; typos in the query; searching for content types the palette doesn't index; slow backend returning results after the scrape.

Related errors


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