Skip to content

Error extractors read response.data.message but FastAPI returns detail: bulk import and SLA failures show generic fallbacks #393

Description

@usmanimamu17-create

---ISSUE---

Problem

Three error extractors read a message field that the backend (FastAPI) does not produce. bulkImportService.extractErrorMessage:

return (
  apiError.response?.data?.message ||
  apiError.message ||
  "Something went wrong during bulk import."
);

and sla.ts's extractErrorMessage:

return (
  axiosError.response?.data?.message ||
  axiosError.message ||
  "An unexpected error occurred."
);

FastAPI error bodies use detail (a string or a [{loc, msg, type}] array), not message. Consequences:

  • Every API validation error surfaces as the generic fallback: a bulk import rejected for a bad row shows "Something went wrong during bulk import." — the actual server reason (row 14: invalid severity) is discarded; SLA calculate/preview failures show "An unexpected error occurred." regardless of the server's message.
  • The two services disagree with the rest of the app: normalizeApiError (src/lib/errors.ts) and handleApiError in src/services/outages.ts do read detail — so error UX varies by service: outages shows real reasons, bulk import and SLA hide them.
  • The mismatch is invisible to typechecking: response?.data is untyped in these helpers, so the wrong field name compiles cleanly.

Root cause

The extractors were written against a message-first API shape before FastAPI's detail convention was established, and were never aligned.

Why this is architecturally hard

  1. The correct fix is one shared error-extraction helper (reading detail, handling the string-vs-array forms, falling back to message) reused by all services — a consolidation (companion issue) that must preserve each service's fallback text.
  2. The array form of detail (422 validation) needs different rendering than the string form (a generic 400) — the extractor must decide what a merged message looks like, aligning with the normalizeApiError field-level work.
  3. Tests must pin the mapping: mock FastAPI-shaped responses ({detail: "..."} and {detail: [{loc, msg}]}) for each service and assert the surfaced message.

Proposed design

Add a shared extractApiErrorMessage (reads detail string/array, then message, then a fallback), use it in bulkImportService, sla.ts, and (optionally) outages.ts's handleApiError, and add table-driven tests per service.

Acceptance criteria

Service

  • Bulk import and SLA failures surface the server's actual reason.
  • Both detail string and array forms map to readable messages.

Tests

  • Table-driven tests cover detail string, detail array, message, and absent-body cases.
  • Existing bulk-import and SLA tests pass.

Out of scope

Field-level 422 rendering (tracked separately) and backend error-shape changes.

Getting started

npm test

Good first files to read: src/services/bulkImportService.ts, src/services/sla.ts, src/services/outages.ts.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardStellar Waveissue-trackingThird CampaignCampaign: Third Campaignarea/apiImported campaign issue labelpriority/highImported campaign issue label

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions