{"record":{"id":"35e7de31a4a5c76f","repo":"jackwener/OpenCLI","slug":"label-returned-404-no-matches","errorCode":null,"errorMessage":"${label} returned 404 (no matches).","messagePattern":"(.+?) returned 404 \\(no matches\\)\\.","errorType":"exception","errorClass":"EmptyResultError","httpStatus":404,"severity":"info","filePath":"clis/openfda/utils.js","lineNumber":35,"sourceCode":"\nexport function requireBoundedInt(value, def, max, name = 'limit') {\n    const n = value == null || value === '' ? def : Number(value);\n    if (!Number.isInteger(n) || n < 1 || n > max) {\n        throw new ArgumentError(`--${name} must be an integer between 1 and ${max}`);\n    }\n    return n;\n}\n\nexport async function openfdaFetch(url, label) {\n    let resp;\n    try {\n        resp = await fetch(url, { headers: { 'User-Agent': UA, accept: 'application/json' } });\n    } catch (err) {\n        throw new CommandExecutionError(`${label} request failed: ${err.message}`);\n    }\n    if (resp.status === 404) {\n        // openFDA returns 404 for \"no matches\" instead of an empty results array.\n        throw new EmptyResultError(label, `${label} returned 404 (no matches).`);\n    }\n    if (resp.status === 429) {\n        throw new CommandExecutionError(`${label} rate-limited (HTTP 429); back off and retry.`);\n    }\n    if (!resp.ok) {\n        throw new CommandExecutionError(`${label} returned HTTP ${resp.status}.`);\n    }\n    let body;\n    try {\n        body = await resp.json();\n    } catch (err) {\n        throw new CommandExecutionError(`${label} returned non-JSON body: ${err.message}`);\n    }\n    return body;\n}\n\n// openFDA returns most string fields as `[string]` arrays — collapse to first\n// element. Preserves `null` (not coerced to empty string) when the slot is","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/openfda/utils.js#L17-L53","documentation":"openFDA signals 'no matches found' by returning HTTP 404 rather than an empty results array. openfdaFetch translates that 404 into an EmptyResultError with this message so callers can treat it as a normal empty outcome instead of a transport error. The label names the originating openfda command.","triggerScenarios":"Any openfda query whose search term(s) match zero records — misspelled drug name, recall filters that never co-occur, an NDC/product string absent from the database. openfdaFetch converts the 404 status before the general !resp.ok branch runs.","commonSituations":"Searching a drug that only exists under another spelling; querying enforcement records for a state/date combo with no recalls; automations that assume every query has results and crash on the empty case.","solutions":["Broaden or correct the search term / filters and retry.","Validate terms against openFDA's own search UI (open.fda.gov) before scripting them.","Catch EmptyResultError in calling code and render 'no results' instead of failing.","If 404 appears for a URL that should match, verify the endpoint path and query encoding (use +AND+ between clauses)."],"exampleFix":"// before\nconst rows = await fetchFoodRecalls({ q: 'Xyzzysnacks' }); // throws EmptyResultError\n// after\ntry {\n  const rows = await fetchFoodRecalls({ q: 'Xyzzysnacks' });\n} catch (e) {\n  if (e instanceof EmptyResultError) return []; // treat as empty\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"function validateRecallQuery({ q }) {\n  if (q != null && q.trim().length < 2) throw new Error('search term too short');\n  return true;\n}","typeGuard":"function isEmptyResult(e) {\n  return e instanceof Error && e.name === 'EmptyResultError';\n}","tryCatchPattern":"try {\n  const rows = await fetchFoodRecalls(filter);\n} catch (e) {\n  if (e instanceof EmptyResultError || /404 \\(no matches\\)/.test(e.message)) {\n    return []; // openFDA 404 == zero matches, not a failure\n  }\n  throw e;\n}","preventionTips":["Always catch EmptyResultError around openfda calls — 404 means 'no matches'.","Verify search terms against open.fda.gov interactively first.","Prefer broader filters, then narrow down.","Encode multi-clause searches with +AND+ / +OR+ correctly."],"tags":["http-404","empty-results","openfda","api"],"backgroundTag":"empty-result-404","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}