Crosstalk-Solutions/project-nomad · error · Error
HTTP ${resp.status} from ${MANIFEST_URL}
Error message
HTTP ${resp.status} from ${MANIFEST_URL} What it means
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.
Source
Thrown at admin/app/jobs/download_drug_data_job.ts:312
}
private async fetchManifest(): Promise<DrugLabelManifest> {
return DownloadDrugDataJob.fetchManifest()
}
/**
* Fetch + parse the openFDA download manifest. The SINGLE source of truth for
* the openFDA manifest call (Maxim 4): the download job uses it on pass 0, and
* the freshness check (DrugReferenceService.checkForUpdate, driven by
* attemptAutoUpdate) reuses it so there is exactly one place that knows the URL and the
* offline-error translation.
*/
static async fetchManifest(): Promise<DrugLabelManifest> {
let json: unknown
try {
const resp = await fetch(MANIFEST_URL)
if (!resp.ok) {
throw new Error(`HTTP ${resp.status} from ${MANIFEST_URL}`)
}
json = await resp.json()
} catch (err) {
const msg = err instanceof Error ? err.message : String(err)
if (
msg.includes('ENOTFOUND') ||
msg.includes('ECONNREFUSED') ||
msg.includes('ECONNRESET') ||
msg.includes('fetch failed')
) {
throw new Error(`No internet — connect to download FDA drug data. (${msg})`)
}
throw err
}
return parseDrugLabelManifest(json)
}
private async writeDownloadState(View on GitHub (pinned to 0bd1c6f4f9)
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.
Example fix
// before
const resp = await fetch(MANIFEST_URL)
if (!resp.ok) throw new Error(`HTTP ${resp.status} from ${MANIFEST_URL}`)
// after — retry with backoff on transient statuses
async function fetchManifestRetry(retries = 3) {
for (let i = 0; i <= retries; i++) {
const resp = await fetch(MANIFEST_URL)
if (resp.ok) return parseDrugLabelManifest(await resp.json())
if (resp.status >= 500 || resp.status === 429) {
await new Promise(r => setTimeout(r, 2 ** i * 1000))
continue
}
throw new Error(`HTTP ${resp.status} from ${MANIFEST_URL}`)
}
throw new Error(`HTTP retries exhausted for ${MANIFEST_URL}`)
} Defensive patterns
Strategy: retry
Validate before calling
// preflight reachability (optional, cheap)
const resp = await fetch(MANIFEST_URL, { method: 'HEAD' }).catch(() => null)
if (!resp?.ok) { /* defer the job instead of failing */ } Try / catch
catch (err) {
if (err instanceof Error && /^HTTP \d+ from /.test(err.message)) {
const status = Number(err.message.match(/^HTTP (\d+)/)?.[1])
if (status >= 500 || status === 429) return retryWithBackoff()
}
throw err
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- No internet — connect to download FDA drug data. (${msg})
- Failed to get auth token from ${registry}: ${response.status
- Failed to download tar file
- Base map assets are missing and could not be downloaded. Ple
- No protomaps builds found
AI-assisted analysis of Crosstalk-Solutions/project-nomad@0bd1c6f4f9 (2026-08-27).
Data as JSON: /api/errors/02fd54d9b15e0d76.
Report an issue: GitHub.