Developer Guide
Error Handling
Every backend error arrives as an RFC 7807 application/problem+json
body (the BE's errorHandler guarantees it — see the BE api-conventions
page). src/lib/errors/ is the single path that parses and presents those
problems. Components never inspect res.status raw and never string-match
error.message.
There is exactly one surfacing API: pushNotification(input) from
src/lib/errors/app-errors.ts. No direct toast.* calls for errors, no
alternate push helpers.
The pipeline
Code
| Layer | Owns |
|---|---|
rfc7807.ts | wire shape — RFC7807Error, safe parse of problem+json |
rfc7807-mapper.ts | problem → domain error mapping (field errors, auth-domain keys) |
app-errors.ts | pushNotification + appErrors store + ImpactLevel |
http-status.ts | status constants/semantics used by api.ts |
toast.ts | the toast primitives pushNotification routes through |
ErrorsPanel.svelte | the shell panel rendering appErrors event cards |
rfc-error-dialog.svelte | dialog that inspects a stored problem entry |
pushNotification contract
- Input is
NotificationInputor an RFC7807 object — auto-detected by the presence oftype(string) +status(number). RFC7807 input is normalized:severity→ impact,title→ scope,detail→ message,internal_code/status/instance→ danger tags. - Always toasts — unless
toast: false(silent panel entry, used by flows that render the error in-place, e.g. login/MFA/change-password). - Adds an
appErrorsevent card — for every impact exceptNONE(NONE is success: toast only, no event card). - Impact → toast style:
CRITICAL→toast.critical(urgent red),HIGH→toast.error,MEDIUM→toast.warning,LOW→toast.info,NONE→toast.success. - i18n —
messageKey/scopeKeyare translated viat(); literalmessage/scopeare the fallback. - Returns the error id for programmatic dismissal.
Code
Contract rules
- Parse, don't guess — api.ts already pushes every detected RFC7807 body; callers only push manually when they consumed the body themselves.
- Field errors ride the problem — validation failures carry
errors[]; forms display them inline rather than toasting rawdetail. - Unhandled rejections are surfaced too —
AppShelllistens onunhandledrejectionand pushes aHIGHnotification, so no async failure is invisible. detailis developer-facing — user copy comes frommessage/messageKey, optionally translated throught(); never render raw serverdetailas the primary message.
Last modified on