Skip to content

Share the apiClient error-message helper across the feedback surface #5440

Description

@CodeGhost21

Use a concise sentence-case title that describes the work item.

Summary

Lift messageForApiError out of FeedbackSubmitForm.tsx into a shared helper and converge the four other feedback call sites on it, so a server-supplied error message reaches the user instead of being replaced by generic copy.

Problem / Context

apiClient rejects with a plain { success: false, error: "..." } object, not an Error (app/src/services/apiClient.ts:109-111,126,130). Every err instanceof Error ? err.message : t(...) against it therefore takes the fallback branch unconditionally — the server's message is discarded 100% of the time, and the user is told "Something went wrong. Please try again." when the backend explained exactly what was wrong.

#5431 fixed this for the submit form with a file-local messageForApiError, which matters there because the backend quality gate returns the reason a draft was refused. The same pattern is still live at four more sites on the same surface, all going through the same apiClient:

  • app/src/components/feedback/FeedbackComments.tsx:56 — comment load
  • app/src/components/feedback/FeedbackComments.tsx:78 — comment post
  • app/src/components/feedback/FeedbackAdminMenu.tsx:42 — admin status update
  • app/src/pages/Feedback.tsx:82 — board load

Raised in review on #5431 and deliberately left out of that PR as scope. Left alone, each site grows its own copy of the fix.

Scope (optional)

In scope: a single exported helper (services-level, next to apiClient, since the shape it decodes is apiClient's), the four call sites above, and unit coverage for both rejection shapes.

Not in scope: changing what apiClient throws. Making it reject with a real Error would be the deeper fix, but it is a cross-cutting change to every consumer in the app, not a feedback-surface cleanup — worth its own issue if wanted.

Note the helper must keep the fallback for a blank or missing error field, and must not surface a raw payload dump — only the error string.

Acceptance criteria

  • Shared helpermessageForApiError(err, fallback) lives in one place, handles the Error shape, the { success, error } shape, and falls back on a blank or absent message.
  • Call sites converged — the four sites above and FeedbackSubmitForm.tsx use it; no instanceof Error check against an apiClient rejection remains on the feedback surface.
  • Tests — unit coverage for all three branches, plus at least one component test proving a server message reaches the screen at a converged site.
  • Diff coverage ≥ 80% — the implementing PR meets the changed-lines coverage gate (Vitest + cargo-llvm-cov, enforced by .github/workflows/ci-lite.yml) when code changes are involved.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions