{"record":{"id":"02fd54d9b15e0d76","repo":"Crosstalk-Solutions/project-nomad","slug":"http-resp-status-from-manifest-url","errorCode":null,"errorMessage":"HTTP ${resp.status} from ${MANIFEST_URL}","messagePattern":"HTTP (.+?) from (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"admin/app/jobs/download_drug_data_job.ts","lineNumber":312,"sourceCode":"  }\n\n  private async fetchManifest(): Promise<DrugLabelManifest> {\n    return DownloadDrugDataJob.fetchManifest()\n  }\n\n  /**\n   * Fetch + parse the openFDA download manifest. The SINGLE source of truth for\n   * the openFDA manifest call (Maxim 4): the download job uses it on pass 0, and\n   * the freshness check (DrugReferenceService.checkForUpdate, driven by\n   * attemptAutoUpdate) reuses it so there is exactly one place that knows the URL and the\n   * offline-error translation.\n   */\n  static async fetchManifest(): Promise<DrugLabelManifest> {\n    let json: unknown\n    try {\n      const resp = await fetch(MANIFEST_URL)\n      if (!resp.ok) {\n        throw new Error(`HTTP ${resp.status} from ${MANIFEST_URL}`)\n      }\n      json = await resp.json()\n    } catch (err) {\n      const msg = err instanceof Error ? err.message : String(err)\n      if (\n        msg.includes('ENOTFOUND') ||\n        msg.includes('ECONNREFUSED') ||\n        msg.includes('ECONNRESET') ||\n        msg.includes('fetch failed')\n      ) {\n        throw new Error(`No internet — connect to download FDA drug data. (${msg})`)\n      }\n      throw err\n    }\n    return parseDrugLabelManifest(json)\n  }\n\n  private async writeDownloadState(","sourceCodeStart":294,"sourceCodeEnd":330,"githubUrl":"https://github.com/Crosstalk-Solutions/project-nomad/blob/0bd1c6f4f9888d577fe232de06ac144bb8337131/admin/app/jobs/download_drug_data_job.ts#L294-L330","documentation":"Thrown by DrugLabelManifestFetcher-like fetchManifest() when fetching MANIFEST_URL returns a non-2xx HTTP status. The fetch itself succeeded at the transport level, but the FDA endpoint responded with an error status, so the manifest JSON is never parsed.","triggerScenarios":"fetch(MANIFEST_URL) resolves with resp.ok false: FDA API is down or returning 5xx, rate limiting (429), moved endpoint (404/301), proxy or captive portal returning 4xx.","commonSituations":"Temporary FDA service outage, rate limit hit during repeated testing, changed/retired endpoint path, corporate proxy intercepting the request, DNS hijack returning an error page.","solutions":["Retry after a short wait — transient 5xx/429 from the FDA API usually clears.","Check the URL in a browser/curl: curl -i $MANIFEST_URL to see the actual status body.","If 404/410, verify the manifest endpoint hasn't changed in the FDA openfda/drug-labels API docs.","If 429, add backoff between job runs or reduce download frequency."],"exampleFix":"// before\nconst resp = await fetch(MANIFEST_URL)\nif (!resp.ok) throw new Error(`HTTP ${resp.status} from ${MANIFEST_URL}`)\n\n// after — retry with backoff on transient statuses\nasync function fetchManifestRetry(retries = 3) {\n  for (let i = 0; i <= retries; i++) {\n    const resp = await fetch(MANIFEST_URL)\n    if (resp.ok) return parseDrugLabelManifest(await resp.json())\n    if (resp.status >= 500 || resp.status === 429) {\n      await new Promise(r => setTimeout(r, 2 ** i * 1000))\n      continue\n    }\n    throw new Error(`HTTP ${resp.status} from ${MANIFEST_URL}`)\n  }\n  throw new Error(`HTTP retries exhausted for ${MANIFEST_URL}`)\n}","handlingStrategy":"retry","validationCode":"// preflight reachability (optional, cheap)\nconst resp = await fetch(MANIFEST_URL, { method: 'HEAD' }).catch(() => null)\nif (!resp?.ok) { /* defer the job instead of failing */ }","typeGuard":null,"tryCatchPattern":"catch (err) {\n  if (err instanceof Error && /^HTTP \\d+ from /.test(err.message)) {\n    const status = Number(err.message.match(/^HTTP (\\d+)/)?.[1])\n    if (status >= 500 || status === 429) return retryWithBackoff()\n  }\n  throw err\n}","preventionTips":["Wrap manifest fetches in retry-with-backoff for 5xx/429.","Cache the last good manifest to ride out short outages.","Alert on repeated non-2xx so endpoint drift is caught early."],"tags":["http","network","fda-api","manifest"],"backgroundTag":"http-error-status","analyzedSha":"0bd1c6f4f9888d577fe232de06ac144bb8337131","analyzedAt":"2026-08-27T05:34:15.424Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}