Crosstalk-Solutions/project-nomad · error · Error

Unexpected FDA manifest format: missing or invalid "total_re

Error message

Unexpected FDA manifest format: missing or invalid "total_records"

What it means

Thrown by parseDrugLabelManifest after export_date validation passes: label['total_records'] must be typeof 'number'. Any other type (missing, string, null) aborts manifest parsing with this error. It guards downstream consumers that rely on total_records for progress reporting and record counting.

Source

Thrown at admin/util/drug_labels.ts:268

  const drug = results['drug'] as Record<string, unknown> | undefined
  if (!drug || typeof drug !== 'object') {
    throw new Error('Unexpected FDA manifest format: missing "results.drug"')
  }

  const label = drug['label'] as Record<string, unknown> | undefined
  if (!label || typeof label !== 'object') {
    throw new Error('Unexpected FDA manifest format: missing "results.drug.label"')
  }

  const export_date = label['export_date']
  if (typeof export_date !== 'string' || export_date.trim() === '') {
    throw new Error('Unexpected FDA manifest format: missing or invalid "export_date"')
  }

  const total_records = label['total_records']
  if (typeof total_records !== 'number') {
    throw new Error('Unexpected FDA manifest format: missing or invalid "total_records"')
  }

  const rawPartitions = label['partitions']
  if (!Array.isArray(rawPartitions) || rawPartitions.length === 0) {
    throw new Error(
      'Unexpected FDA manifest format: "partitions" is missing or empty'
    )
  }

  const partitions: DrugLabelPartition[] = []
  for (const p of rawPartitions as unknown[]) {
    if (typeof p !== 'object' || p === null) {
      process.stderr.write('[parseDrugLabelManifest] Skipping non-object partition\n')
      continue
    }
    const part = p as Record<string, unknown>
    if (typeof part['file'] !== 'string' || (part['file'] as string).trim() === '') {
      process.stderr.write(

View on GitHub (pinned to 0bd1c6f4f9)

Solutions

  1. Dump the manifest and check typeof results.drug.label.total_records in the actual response.
  2. If the API now returns a numeric string, coerce defensively: Number(...) with NaN check inside parseDrugLabelManifest.
  3. Update test fixtures to match the real API shape.
  4. Confirm you are hitting the documented FDA bulk-download endpoint version.

Example fix

// before
const total_records = label['total_records']
if (typeof total_records !== 'number') {
  throw new Error('Unexpected FDA manifest format: missing or invalid "total_records"')
}
// after
const raw = label['total_records']
const total_records = typeof raw === 'number' ? raw : typeof raw === 'string' && /^\d+$/.test(raw) ? Number(raw) : NaN
if (!Number.isFinite(total_records)) {
  throw new Error(`Unexpected FDA manifest format: "total_records" was ${JSON.stringify(raw)}`)
}
Defensive patterns

Strategy: validation

Validate before calling

const tr = label?.['total_records']
if (typeof tr !== 'number' && !(typeof tr === 'string' && /^\d+$/.test(tr))) {
  // refuse to parse; report schema problem
}

Type guard

function isValidTotalRecords(v: unknown): boolean {
  return typeof v === 'number' && Number.isFinite(v) && v >= 0
}

Try / catch

try { parseDrugLabelManifest(json) } catch (e) { if (e.message.includes('total_records')) reportSchemaDrift(json); throw e }

Prevention

When it happens

Trigger: The FDA manifest's results.drug.label object contains total_records as a JSON string ("42000" instead of 42000), the field is omitted, or an intermediate proxy/re-serializer converts numbers to strings (e.g. some JSON transform pipelines or hand-edited fixtures).

Common situations: Upstream API starts serializing counts as strings; test fixtures hand-written with quoted numbers; a caching layer that JSON round-trips values through a form that loses number typing; API version mismatch.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Crosstalk-Solutions/project-nomad@0bd1c6f4f9 (2026-08-27). Data as JSON: /api/errors/881340a979520cd4. Report an issue: GitHub.