{"record":{"id":"e146859ef14fc3d1","repo":"Crosstalk-Solutions/project-nomad","slug":"msg","errorCode":null,"errorMessage":"${msg}","messagePattern":"\\$\\{msg\\}","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"admin/app/controllers/conditions_controller.ts","lineNumber":111,"sourceCode":"\n      if (params.slug) {\n        const result = await this.service.drugsForSlug(params.slug, params.limit, filterOpts)\n        if (!result) {\n          return response.notFound({ error: 'Condition not found' })\n        }\n        return remediesOn ? result : { ...result, remedies: [] }\n      }\n\n      if (params.q) {\n        const result = await this.service.drugsForFreeText(params.q, params.limit, filterOpts)\n        return remediesOn ? result : { ...result, remedies: [] }\n      }\n\n      return response.badRequest({ error: 'Provide a slug or q query parameter' })\n    } catch (err) {\n      const msg = err instanceof Error ? err.message : String(err)\n      logger.warn(`[ConditionsController] drugsApi failed: ${msg}`)\n      return response.badRequest({ error: msg })\n    }\n  }\n}\n","sourceCodeStart":93,"sourceCodeEnd":115,"githubUrl":"https://github.com/Crosstalk-Solutions/project-nomad/blob/0bd1c6f4f9888d577fe232de06ac144bb8337131/admin/app/controllers/conditions_controller.ts#L93-L115","documentation":"This is a catch-all error handler in ConditionsController.drugsApi that surfaces any thrown error from the external drugs API call as a 400 Bad Request with the raw error message. It is not a specific library error; whatever upstream failure occurred (network, timeout, invalid API key, malformed query) gets flattened into this response. The `message=\"${msg}\"` form indicates the log line captures the interpolated upstream message.","triggerScenarios":"Calling GET /api/conditions/drugs without a slug or q parameter returns a deterministic 400; alternatively the upstream drugs API request fails (DNS failure, 401/403 from missing API key, timeout, or non-JSON response) and the caught error message is relayed here.","commonSituations":"Missing or expired DRUGS_API_KEY env var in the admin service; upstream drugs endpoint changed or is rate-limiting; developers testing locally without network access to the third-party API; frontend sending both slug and q or neither.","solutions":["Check the server logs for the preceding [ConditionsController] drugsApi failed line to see the real upstream message","Verify the request includes exactly one of slug or q query parameter","Confirm the drugs API credentials/base URL env vars are set and valid","If upstream is down/rate-limited, retry later or add caching/fallback for drug lookups"],"exampleFix":"// before\nconst res = await fetch(`/api/conditions/drugs`)\n// after\nconst res = await fetch(`/api/conditions/drugs?q=${encodeURIComponent(query)}`)\nif (!res.ok) console.error(await res.json())","handlingStrategy":"validation","validationCode":"const params = new URLSearchParams()\nif (slug) params.set('slug', slug)\nelse if (q?.trim()) params.set('q', q.trim())\nif (![...params.keys()].length) throw new Error('slug or q required')\nconst res = await fetch(`/api/conditions/drugs?${params}`)\nif (!res.ok) { /* surface res.error to UI, fall back to cached list */ }","typeGuard":"const isApiError = (b: unknown): b is { error: string } =>\n  typeof b === 'object' && b !== null && typeof (b as any).error === 'string''\n\nasync function parseError(res: Response): Promise<string> {\n  const body = await res.json().catch(() => null)\n  return isApiError(body) ? body.error : `HTTP ${res.status}`\n}","tryCatchPattern":"try {\n  return await conditionsApi.drugs({ q })\n} catch (err) {\n  // HTTP 400 with { error }; show message, fall back to cached results\n  return cachedDrugs\n}","preventionTips":["Always send exactly one of slug or q, URL-encoded and non-empty","Cache drug lookup results so upstream outages degrade gracefully","Monitor for [ConditionsController] drugsApi failed warns to catch credential/upstream issues early"],"tags":["api","upstream","bad-request","external-service"],"backgroundTag":"upstream-api-failure","analyzedSha":"0bd1c6f4f9888d577fe232de06ac144bb8337131","analyzedAt":"2026-08-27T05:34:15.424Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}