jackwener/OpenCLI · warning · EmptyResultError

openFDA returned no food recall records matching the filter.

Error message

openFDA returned no food recall records matching the filter.

What it means

food-recall queries openFDA's /food/enforcement.json endpoint and throws EmptyResultError when the filtered result list is empty. Because openFDA returns HTTP 404 for zero matches (converted by openfdaFetch) and also allows genuinely empty arrays, the CLI normalizes both cases into this single 'no records' error. The message reflects the user's filter(s) yielding nothing.

Source

Thrown at clis/openfda/food-recall.js:44

        'productDescription', 'reasonForRecall', 'productQuantity',
        'distributionPattern', 'reportDate', 'recallInitiationDate', 'terminationDate',
    ],
    func: async (args) => {
        const limit = requireBoundedInt(args.limit, 10, 100);
        const filters = [];
        if (args.query) filters.push(String(args.query).trim());
        if (args.status) filters.push(`status:"${String(args.status).trim()}"`);
        if (args.classification) filters.push(`classification:"${String(args.classification).trim()}"`);
        // URLSearchParams percent-encodes the `+AND+` separator that openFDA's
        // Lucene parser treats specially, so build the query string by hand.
        const qs = filters.length
            ? `search=${filters.map(f => encodeURIComponent(f)).join('+AND+')}&limit=${limit}`
            : `limit=${limit}`;
        const url = `${OPENFDA_BASE}/food/enforcement.json?${qs}`;
        const body = await openfdaFetch(url, 'openfda food-recall');
        const list = Array.isArray(body?.results) ? body.results : [];
        if (!list.length) {
            throw new EmptyResultError('openfda food-recall', 'openFDA returned no food recall records matching the filter.');
        }
        return list.map((r, i) => ({
            rank: i + 1,
            recallNumber: r?.recall_number ?? null,
            status: r?.status ?? null,
            classification: r?.classification ?? null,
            voluntary: r?.voluntary_mandated ?? null,
            recallingFirm: r?.recalling_firm ?? null,
            city: r?.city ?? null,
            state: r?.state ?? null,
            country: r?.country ?? null,
            productDescription: r?.product_description ?? null,
            reasonForRecall: r?.reason_for_recall ?? null,
            productQuantity: r?.product_quantity ?? null,
            distributionPattern: r?.distribution_pattern ?? null,
            reportDate: r?.report_date ?? null,
            recallInitiationDate: r?.recall_initiation_date ?? null,
            terminationDate: r?.termination_date ?? null,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Widen the date range or drop the most restrictive filter and re-run.
  2. Verify the exact terminology FDA uses (recall classification I/II/III, status 'ongoing'/'completed') via a direct curl to api.fda.gov.
  3. Search by a broader product keyword instead of an exact brand string.
  4. Treat the empty result as a valid business outcome in the calling script rather than an exception.

Example fix

// before
fetchFoodRecalls({ state: 'CA', from: '2026-08-25', to: '2026-08-26' }); // too narrow
// after
fetchFoodRecalls({ state: 'CA', from: '2026-08-01', to: '2026-08-29' });
Defensive patterns

Strategy: try-catch

Validate before calling

function validateRecallFilter(f = {}) {
  const validClass = ['I', 'II', 'III'];
  if (f.classification && !validClass.includes(f.classification)) {
    throw new Error(`classification must be one of ${validClass.join('/')}`);
  }
  if (f.from && f.to && f.from > f.to) throw new Error('date range inverted');
  return true;
}

Type guard

function hasResults(body) {
  return body != null && Array.isArray(body.results) && body.results.length > 0;
}

Try / catch

try {
  const rows = await fetchFoodRecalls(filter);
} catch (e) {
  if (e instanceof EmptyResultError) return []; // no recalls matched
  throw e;
}

Prevention

When it happens

Trigger: Filters like classification, status, date range, or a search term for /food/enforcement.json match zero recall records — e.g. filtering recalls for a product never recalled, or a date window with no enforcement actions.

Common situations: Narrow date range (last week) with no food recalls; filtering on a classification/status combination that never co-occurs; a product name spelled differently in FDA records ('Hy-Vee' vs brand spellings).

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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