Crosstalk-Solutions/project-nomad · error
${msg}
Error message
${msg} What it means
DrugReferenceController.search wraps its search pipeline (query parsing + upstream drug reference search) in a try/catch and converts any exception into a 400 Bad Request carrying the raw error message. Because the catch is generic, the 400 does not necessarily mean a client mistake — infrastructure failures are also reported as 400. The real cause is always in the preceding [DrugReferenceController] search failed warn log.
Source
Thrown at admin/app/controllers/drug_reference_controller.ts:115
* Returns a slim collapsed result list (brand+generic pairs).
*/
async search({ request, response }: HttpContext) {
try {
const params = await request.validateUsing(searchDrugValidator)
const results = await this.service.search(params.q, {
productType: params.product_type,
route: params.route,
sort: params.sort,
limit: params.limit,
offset: params.offset,
scope: params.scope,
})
return { results }
} catch (err) {
const msg = err instanceof Error ? err.message : String(err)
logger.warn(`[DrugReferenceController] search failed: ${msg}`)
return response.badRequest({ error: msg })
}
}
/**
* GET /api/drug-reference/status
* Returns the live ingest status DTO.
*/
async status({ response }: HttpContext) {
try {
const status = await this.service.getIngestStatus()
return status
} catch (err) {
const msg = err instanceof Error ? err.message : String(err)
logger.error(`[DrugReferenceController] status failed: ${msg}`)
return response.internalServerError({ error: 'Could not read ingest status' })
}
}
/**View on GitHub (pinned to 0bd1c6f4f9)
Solutions
- Check server logs for the [DrugReferenceController] search failed warn with the actual message
- If the error mentions index/ingest, hit GET /api/drug-reference/status and run the ingest/download flow before searching
- Sanitize the q parameter and pagination values on the client
- Verify reference provider credentials/env config
Example fix
// before
fetch('/api/drug-reference/search?q=')
// after
if (!query.trim()) throw new Error('empty query')
fetch(`/api/drug-reference/search?q=${encodeURIComponent(query.trim())}&page=1&pageSize=20`) Defensive patterns
Strategy: validation
Validate before calling
const q = query.trim()
if (q.length < 2) return showHint('Type at least 2 characters')
const page = Number.isInteger(pageNum) && pageNum > 0 ? pageNum : 1
const res = await fetch(`/api/drug-reference/search?q=${encodeURIComponent(q)}&page=${page}`)
if (!res.ok) return handleSearchError(await res.json()) Type guard
const isSearchErrorResponse = (b: unknown): b is { error: string } =>
typeof b === 'object' && b !== null && typeof (b as any).error === 'string'
async function safeSearch(q: string) {
const res = await fetch(`/api/drug-reference/search?q=${encodeURIComponent(q)}`)
const body = await res.json().catch(() => null)
if (!res.ok) return { results: [], error: isSearchErrorResponse(body) ? body.error : `HTTP ${res.status}` }
return body as { results: unknown[] }
} Try / catch
try {
return await drugRef.search(q, page)
} catch (err) {
// check ingest status before showing a hard error
const status = await drugRef.status()
if (!status.ingested) return { results: [], hint: 'Reference data not ingested yet' }
throw err
} Prevention
- Debounce search and require a minimum query length before calling
- Check /api/drug-reference/status after deploy and run ingest before enabling search UI
- Validate pagination params client-side (positive integers, bounded pageSize)
When it happens
Trigger: GET /api/drug-reference/search with a malformed or empty q, an unsupported page/pageSize value, or when the underlying reference service throws (empty index, ingest never ran, upstream provider error). Called by the results endpoint, so navigating to search results with a bad or stale query triggers it.
Common situations: Searching before the drug-reference ingest has completed (empty index); passing non-numeric pagination params; reference provider API key missing; stale frontend sending a query format from an older API version.
Related errors
- ${msg}
- Filename is required
- Invalid document slug
- Invalid PMTiles file URL: ${url}. URL must end with .pmtiles
- Could not determine filename from URL
AI-assisted analysis of Crosstalk-Solutions/project-nomad@0bd1c6f4f9 (2026-08-27).
Data as JSON: /api/errors/5603dc3abacb2466.
Report an issue: GitHub.